From 7e60bb04e5a59448e5dc8ad9e690a06c7c797498 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 Jul 2012 15:12:08 -0400 Subject: [PATCH 01/11] Add an exception on remote group join --- plugins/OStatus/actions/ostatusgroup.php | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/OStatus/actions/ostatusgroup.php b/plugins/OStatus/actions/ostatusgroup.php index e2c4121c3f..e5ed21bbf5 100644 --- a/plugins/OStatus/actions/ostatusgroup.php +++ b/plugins/OStatus/actions/ostatusgroup.php @@ -146,6 +146,7 @@ class OStatusGroupAction extends OStatusSubAction try { $user->joinGroup($group); } catch (Exception $e) { + common_log(LOG_ERR, "Exception on remote group join: " . $e->getMessage()); // TRANS: OStatus remote group subscription dialog error. $this->showForm(_m('Remote group join failed!')); return; From d5564fb8d826019d4cd969b8b2d5a16e5e5ef3df Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 Jul 2012 15:14:35 -0400 Subject: [PATCH 02/11] Add a trace, too --- plugins/OStatus/actions/ostatusgroup.php | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/OStatus/actions/ostatusgroup.php b/plugins/OStatus/actions/ostatusgroup.php index e5ed21bbf5..e110c690d0 100644 --- a/plugins/OStatus/actions/ostatusgroup.php +++ b/plugins/OStatus/actions/ostatusgroup.php @@ -147,6 +147,7 @@ class OStatusGroupAction extends OStatusSubAction $user->joinGroup($group); } catch (Exception $e) { common_log(LOG_ERR, "Exception on remote group join: " . $e->getMessage()); + common_log(LOG_ERR, $e->getTraceAsString()); // TRANS: OStatus remote group subscription dialog error. $this->showForm(_m('Remote group join failed!')); return; From 78a8eb5b6ebac0afe3e899990860c6f18c013f52 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 09:43:05 -0400 Subject: [PATCH 03/11] Squashed commit of the following: commit cd43ac412c90722e3b83ec750d9232a2ac2f12c9 Merge: dad72cc adaf175 Author: Evan Prodromou Date: Mon Jul 9 09:41:05 2012 -0400 Merge commit 'refs/merge-requests/196' of git://gitorious.org/statusnet/mainline into merge-requests/196 commit adaf17552d3ab35d451c00cdb32d87a107e0e56a Author: Jeremy Pope Date: Thu Jul 5 12:33:06 2012 -0500 fix for XMPP high CPU usage - issue no 3232 commit e573e8ee6690af94259ff8793a84652a139d0662 Author: Jeremy Pope Date: Thu Jul 5 12:30:34 2012 -0500 fix for queuedaemon and imdaemon not being stopped by stopdaemons.sh --- plugins/Xmpp/XmppPlugin.php | 4 ++-- scripts/stopdaemons.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/Xmpp/XmppPlugin.php b/plugins/Xmpp/XmppPlugin.php index 50950d8570..0f82ed041c 100644 --- a/plugins/Xmpp/XmppPlugin.php +++ b/plugins/Xmpp/XmppPlugin.php @@ -380,12 +380,12 @@ class XmppPlugin extends ImPlugin if ($pl['type'] != 'chat') { $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from: " . $pl['xml']->toString()); - return; + return true; } if (mb_strlen($pl['body']) == 0) { $this->log(LOG_WARNING, "Ignoring message with empty body from $from: " . $pl['xml']->toString()); - return; + return true; } $this->handleIncoming($from, $pl['body']); diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index bc1230e645..45a7d5cc8b 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -23,8 +23,8 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` -for f in ombhandler smshandler pinghandler \ - twitterhandler facebookhandler \ +for f in ombhandler smshandler pinghandler queuedaemon \ + twitterhandler facebookhandler imdaemon \ twitterstatusfetcher synctwitterfriends pluginhandler rsscloudhandler; do FILES="$DIR/$f.*.pid" From 206c09068884f701d9dc295c851a1216c5839ff3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 12:55:05 -0400 Subject: [PATCH 04/11] Squashed commit of the following: commit 7ef19ab918cc9805abb8d01e8220ae4ed63155d7 Author: Evan Prodromou Date: Mon Jul 9 12:53:29 2012 -0400 Show link to facebook account on profile block If you've logged in with Facebook, show a link to that account on the profile block. commit b56967479c009d702150791944dbd80746ee3ba1 Author: Evan Prodromou Date: Mon Jul 9 12:28:34 2012 -0400 Add profile link from profile block to Twitter account Add a profile link to Twitter for accounts that are linked via Twitter login. commit 181e441fd03c6034e737f6a3dae115557aa3e1aa Author: Evan Prodromou Date: Mon Jul 9 11:57:56 2012 -0400 OpenID shows other account links commit ef7357883dad9e34af2746e1c6a41ea826d7c992 Author: Evan Prodromou Date: Mon Jul 9 11:53:12 2012 -0400 Add a profile link for OpenIDs OpenID plugin now adds a profile link for each OpenID on the account. commit 093d26b95bc453686d24c42f5a8f4739cb338fd2 Author: Evan Prodromou Date: Mon Jul 9 11:15:18 2012 -0400 Better array access commit 49d47257efdcae2101b589a1f825872bdd70667c Author: Evan Prodromou Date: Mon Jul 9 10:57:16 2012 -0400 Show list of other accounts in profile block We add a group of "rel-me" links to other user accounts on the Web. This is mostly useful for when you've used OpenID, Twitter, or Facebook login to associate a remote account. There's an extension to the profileblock recipe to show the links as little icons; there's a new hook in accountprofileblock to get such links from plugins. There's a modification to the base theme to show the icons correctly (I think). --- EVENTS.txt | 6 ++ lib/accountprofileblock.php | 9 +++ lib/defaultprofileblock.php | 5 ++ lib/groupprofileblock.php | 5 ++ lib/profileblock.php | 26 ++++++++ .../FacebookBridge/FacebookBridgePlugin.php | 63 ++++++++++++++++++ plugins/FacebookBridge/images/f_logo.png | Bin 0 -> 481 bytes plugins/OpenID/OpenIDPlugin.php | 26 ++++++++ plugins/OpenID/icons/openid-16x16.gif | Bin 0 -> 328 bytes plugins/TwitterBridge/TwitterBridgePlugin.php | 28 ++++++++ .../icons/twitter-bird-white-on-blue.png | Bin 0 -> 433 bytes theme/base/css/display.css | 5 ++ 12 files changed, 173 insertions(+) create mode 100644 plugins/FacebookBridge/images/f_logo.png create mode 100644 plugins/OpenID/icons/openid-16x16.gif create mode 100644 plugins/TwitterBridge/icons/twitter-bird-white-on-blue.png diff --git a/EVENTS.txt b/EVENTS.txt index 0c08a46478..49940e467f 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -1450,3 +1450,9 @@ EndNoticeListPrefill: After pre-filling a list of notices with extra data - &$profiles: Profiles that were pre-filled - $avatarSize: The avatar size for the list +OtherAccountProfiles: Hook to add account profiles to a user account profile block +- $profile: the Profile being shown +- &$others: Modifiable array of profile info arrays. Each one has the following fields: + href: link to the profile + text: text for the profile + image: mini image for the profile diff --git a/lib/accountprofileblock.php b/lib/accountprofileblock.php index 4eca000c9e..f49c73aeab 100644 --- a/lib/accountprofileblock.php +++ b/lib/accountprofileblock.php @@ -94,6 +94,15 @@ class AccountProfileBlock extends ProfileBlock return $this->profile->bio; } + function otherProfiles() + { + $others = array(); + + Event::handle('OtherAccountProfiles', array($this->profile, &$others)); + + return $others; + } + function showTags() { $cur = common_current_user(); diff --git a/lib/defaultprofileblock.php b/lib/defaultprofileblock.php index b8af14ac21..78c7c4a118 100644 --- a/lib/defaultprofileblock.php +++ b/lib/defaultprofileblock.php @@ -86,4 +86,9 @@ class DefaultProfileBlock extends AccountProfileBlock { return null; } + + function otherProfiles() + { + return array(); + } } \ No newline at end of file diff --git a/lib/groupprofileblock.php b/lib/groupprofileblock.php index 58e553a4c2..87ec174dc6 100644 --- a/lib/groupprofileblock.php +++ b/lib/groupprofileblock.php @@ -85,6 +85,11 @@ class GroupProfileBlock extends ProfileBlock return $this->group->description; } + function otherProfiles() + { + return array(); + } + function showActions() { $cur = common_current_user(); diff --git a/lib/profileblock.php b/lib/profileblock.php index eb19a1a9aa..697ff8d340 100644 --- a/lib/profileblock.php +++ b/lib/profileblock.php @@ -61,6 +61,7 @@ abstract class ProfileBlock extends Widget $this->showName(); $this->showLocation(); $this->showHomepage(); + $this->showOtherProfiles(); $this->showDescription(); $this->showTags(); } @@ -133,6 +134,31 @@ abstract class ProfileBlock extends Widget } } + function showOtherProfiles() + { + $otherProfiles = $this->otherProfiles(); + + if (!empty($otherProfiles)) { + + $this->out->elementStart('ul', + array('class' => 'profile_block_otherprofile_list')); + + foreach ($otherProfiles as $otherProfile) { + $this->out->elementStart('li'); + $this->out->elementStart('a', + array('href' => $otherProfile['href'], + 'rel' => 'me', + 'class' => 'profile_block_otherprofile', + 'alt' => $otherProfile['text'])); + $this->out->element('img', + array('src' => $otherProfile['image'], + 'class' => 'profile_block_otherprofile_icon')); + $this->out->elementEnd('a'); + $this->out->elementEnd('li'); + } + } + } + function avatarSize() { return AVATAR_PROFILE_SIZE; diff --git a/plugins/FacebookBridge/FacebookBridgePlugin.php b/plugins/FacebookBridge/FacebookBridgePlugin.php index bf16da337d..289f219112 100644 --- a/plugins/FacebookBridge/FacebookBridgePlugin.php +++ b/plugins/FacebookBridge/FacebookBridgePlugin.php @@ -559,6 +559,69 @@ ENDOFSCRIPT; return true; } + /** + * Add links in the user's profile block to their Facebook profile URL. + * + * @param Profile $profile The profile being shown + * @param Array &$links Writeable array of arrays (href, text, image). + * + * @return boolean hook value (true) + */ + + function onOtherAccountProfiles($profile, &$links) + { + $fuser = null; + + $flink = Foreign_link::getByUserID($profile->id, FACEBOOK_SERVICE); + + if (!empty($flink)) { + + $fuser = $this->getFacebookUser($flink->foreign_id); + + if (!empty($fuser)) { + $links[] = array("href" => $fuser->link, + "text" => sprintf(_("@%s on Facebook"), $fuser->name), + "image" => $this->path("images/f_logo.png")); + } + } + + return true; + } + + function getFacebookUser($id) { + + $key = Cache::key(sprintf("FacebookBridgePlugin:userdata:%d", $id)); + + $c = Cache::instance(); + + if ($c) { + $obj = $c->get($key); + if ($obj) { + return $obj; + } + } + + $url = sprintf("https://graph.facebook.com/%s", $id); + $client = new HTTP_Client(); + $resp = $client->get($url); + + if (!$resp->isOK()) { + return null; + } + + $user = json_decode($resp->getBody()); + + if ($user->error) { + return null; + } + + if ($c) { + $c->set($key, $user); + } + + return $user; + } + /* * Add version info for this plugin * diff --git a/plugins/FacebookBridge/images/f_logo.png b/plugins/FacebookBridge/images/f_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b54e21cadfa783b0c258d71328640ad813b587a8 GIT binary patch literal 481 zcmV<70UrK|P)Uq4o)@Q^;dz+fe9)`+-;PcyOoac1s+RgA>8)1PG;`jA8DSu`Mn`(6o%0i8 zL-RAw1_z42liJ6PA5kcBuiE>$sqxh}FY+|0G}bKLy39aCZJV84)HCM+ zG%xMxMI#JMezAul-E0p)UnF$r-b|Di12M%o5HSGSom7Z0`s7hxD0ji4NB|6!3ln3* zV%T~A>o^frWSO_@ZW}<=db#x1 literal 0 HcmV?d00001 diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index ed6d6534c0..d5c5c303c2 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -814,4 +814,30 @@ class OpenIDPlugin extends Plugin return true; } + + /** + * Add links in the user's profile block to their OpenID URLs. + * + * @param Profile $profile The profile being shown + * @param Array &$links Writeable array of arrays (href, text, image). + * + * @return boolean hook value (true) + */ + + function onOtherAccountProfiles($profile, &$links) + { + $oid = new User_openid(); + + $oid->user_id = $profile->id; + + if ($oid->find()) { + while ($oid->fetch()) { + $links[] = array('href' => $oid->display, + 'text' => _('OpenID'), + 'image' => $this->path("icons/openid-16x16.gif")); + } + } + + return true; + } } diff --git a/plugins/OpenID/icons/openid-16x16.gif b/plugins/OpenID/icons/openid-16x16.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2d8377db023a3915cc9e8c2f1f5c7462622f0a1 GIT binary patch literal 328 zcmZ?wbhEHb6krfwxXQrr>({UQ_wR4qxN*;(J#*&FS-N!TvSrKGuV4S?%F;i7{_Nbj z^V6qK`}XadJ9qBs)2Dx~3p;V*#MZ4_j~qF&aN)v#|Nb2~aNyvg9 ztXT2$=g%EGcI@80`{m1*Z{NOs{rdIFl`EeF4W-ruOthu2f ztl_Mdp@*QzZPDcui{^-N`o3xq@(UMrZh5FF-w`Y#$*8QNq^Zf+5a!Y$(d{Fk$;RMZ d?jf!z+?DC8mZr!$-G@O{mX$wbm9ry*H2@d`j5z=R literal 0 HcmV?d00001 diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index d733f71c56..25d8a423ca 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -557,4 +557,32 @@ class TwitterBridgePlugin extends Plugin } return true; } + + /** + * Add links in the user's profile block to their Twitter profile URL. + * + * @param Profile $profile The profile being shown + * @param Array &$links Writeable array of arrays (href, text, image). + * + * @return boolean hook value (true) + */ + + function onOtherAccountProfiles($profile, &$links) + { + $fuser = null; + + $flink = Foreign_link::getByUserID($profile->id, TWITTER_SERVICE); + + if (!empty($flink)) { + $fuser = $flink->getForeignUser(); + + if (!empty($fuser)) { + $links[] = array("href" => $fuser->uri, + "text" => sprintf(_("@%s on Twitter"), $fuser->nickname), + "image" => $this->path("icons/twitter-bird-white-on-blue.png")); + } + } + + return true; + } } diff --git a/plugins/TwitterBridge/icons/twitter-bird-white-on-blue.png b/plugins/TwitterBridge/icons/twitter-bird-white-on-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..2c42b0823e1ad7f11567c60de6e1ddbdfe8600cd GIT binary patch literal 433 zcmV;i0Z#sjP)Y5S_W*csVav z9BM*9h*(&Og^i%Z*3LpJe}R>Sou!R}SctXw1H{fo3p=&2GLTvjf*3r#Q{-+h+1;@? z-F%7!oMIPd_RX93c5wRi5e5kh28=%d^c#SP%xMb6VK(71j^J`Md7fU8q?4tw&09Z3 z2&oU|M^{TOBGzMdS&I&q;s_)lzVPTK0ZpPZ08Cfa01&0HGA_^0| zR|(D@KC`^zb1~f|A{t`o+03&Ux4;)FNOUB1d+!bgL~LrP$Lcwf1b~2u(EGXtfHrgR bf4B7uTuzHLl#7Af00000NkvXXu0mjfFlet2 literal 0 HcmV?d00001 diff --git a/theme/base/css/display.css b/theme/base/css/display.css index d2d07c4cec..483aa15ff7 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -2549,6 +2549,11 @@ display:none; display:none; } +.profile_block_otherprofile_list li { + display: inline; + list-style-type: none; +} + /*end of @media screen, projection, tv*/ From 1c9dc7257d5be1b5354984de3a7f32c5a4fa8c0f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 13:21:14 -0400 Subject: [PATCH 05/11] Finish out the ul for other accounts --- lib/profileblock.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/profileblock.php b/lib/profileblock.php index 697ff8d340..2a71f284c3 100644 --- a/lib/profileblock.php +++ b/lib/profileblock.php @@ -156,6 +156,8 @@ abstract class ProfileBlock extends Widget $this->out->elementEnd('a'); $this->out->elementEnd('li'); } + + $this->out->elementEnd('ul'); } } From 18ebca5b8fa89dfbd4dcbf73185e3c551f57d27a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 13:37:33 -0400 Subject: [PATCH 06/11] Better cache key, httpclient reference in FacebookBridgePlugin --- plugins/FacebookBridge/FacebookBridgePlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/FacebookBridge/FacebookBridgePlugin.php b/plugins/FacebookBridge/FacebookBridgePlugin.php index 289f219112..64a73ed126 100644 --- a/plugins/FacebookBridge/FacebookBridgePlugin.php +++ b/plugins/FacebookBridge/FacebookBridgePlugin.php @@ -590,7 +590,7 @@ ENDOFSCRIPT; function getFacebookUser($id) { - $key = Cache::key(sprintf("FacebookBridgePlugin:userdata:%d", $id)); + $key = Cache::key(sprintf("FacebookBridgePlugin:userdata:%s", $id)); $c = Cache::instance(); @@ -602,7 +602,7 @@ ENDOFSCRIPT; } $url = sprintf("https://graph.facebook.com/%s", $id); - $client = new HTTP_Client(); + $client = new HTTPClient(); $resp = $client->get($url); if (!$resp->isOK()) { From b55356491cdffab626aec7d697c73bc40745fa0f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 13:46:32 -0400 Subject: [PATCH 07/11] $otherProfile['href'], 'rel' => 'me', 'class' => 'profile_block_otherprofile', - 'alt' => $otherProfile['text'])); + 'title' => $otherProfile['text'])); $this->out->element('img', array('src' => $otherProfile['image'], 'class' => 'profile_block_otherprofile_icon')); From 16a091a43084c26c4660b2e711a11d4e228a0212 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 13:57:51 -0400 Subject: [PATCH 08/11] Remove "@" from hover text; most people don't use "@" on Facebook --- plugins/FacebookBridge/FacebookBridgePlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/FacebookBridge/FacebookBridgePlugin.php b/plugins/FacebookBridge/FacebookBridgePlugin.php index 64a73ed126..07a149785c 100644 --- a/plugins/FacebookBridge/FacebookBridgePlugin.php +++ b/plugins/FacebookBridge/FacebookBridgePlugin.php @@ -580,7 +580,7 @@ ENDOFSCRIPT; if (!empty($fuser)) { $links[] = array("href" => $fuser->link, - "text" => sprintf(_("@%s on Facebook"), $fuser->name), + "text" => sprintf(_("%s on Facebook"), $fuser->name), "image" => $this->path("images/f_logo.png")); } } From 51687cd4dbd830f7f2ce16d321620871bc66ede3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 15:59:10 -0400 Subject: [PATCH 09/11] Fix formatting of header --- plugins/OpenID/OpenIDPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index d5c5c303c2..ff2e2adb5b 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -20,7 +20,7 @@ * @category Plugin * @package StatusNet * @author Evan Prodromou - * @author Craig Andrews + * @author Craig Andrews * @copyright 2009-2010 StatusNet, Inc. * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 From ec3f9b199f696e47403d6b672d7c217ba8e8785e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 9 Jul 2012 16:51:36 -0400 Subject: [PATCH 10/11] Squashed commit of the following: commit 90620124a20d8c9da19b26920b02b521766c42e4 Author: Evan Prodromou Date: Mon Jul 9 16:50:05 2012 -0400 Add a checkbox to hide OpenID links commit 47a4a5824208868bd5f4f163456f8e08380e5f36 Author: Evan Prodromou Date: Mon Jul 9 16:35:15 2012 -0400 Don't show the profile links if the hide_profile_link flag is set commit eafd4b8ba1f7c06c92e5279b1a703c5534aa7255 Author: Evan Prodromou Date: Mon Jul 9 16:30:23 2012 -0400 class for user_openid_prefs table commit 60e3e3825b20745c08b4d30dbbcac2d7ce604a2f Author: Evan Prodromou Date: Mon Jul 9 16:29:15 2012 -0400 add User_openid_prefs table and class --- plugins/OpenID/OpenIDPlugin.php | 26 ++++--- plugins/OpenID/User_openid_prefs.php | 100 +++++++++++++++++++++++++++ plugins/OpenID/openidsettings.php | 57 +++++++++++++++ 3 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 plugins/OpenID/User_openid_prefs.php diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index ff2e2adb5b..3d8dab8213 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -362,10 +362,9 @@ class OpenIDPlugin extends Plugin require_once dirname(__FILE__) . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'User_openid': - require_once dirname(__FILE__) . '/User_openid.php'; - return false; + case 'User_openid_prefs': case 'User_openid_trustroot': - require_once dirname(__FILE__) . '/User_openid_trustroot.php'; + require_once dirname(__FILE__) . '/' . $cls . '.php'; return false; case 'Auth_OpenID_TeamsExtension': case 'Auth_OpenID_TeamsRequest': @@ -574,6 +573,8 @@ class OpenIDPlugin extends Plugin null, false), new ColumnDef('modified', 'timestamp'))); + $schema->ensureTable('user_openid_prefs', User_openid_prefs::schemaDef()); + /* These are used by JanRain OpenID library */ $schema->ensureTable('oid_associations', @@ -826,15 +827,20 @@ class OpenIDPlugin extends Plugin function onOtherAccountProfiles($profile, &$links) { - $oid = new User_openid(); + $prefs = User_openid_prefs::staticGet('user_id', $profile->id); - $oid->user_id = $profile->id; + if (empty($prefs) || !$prefs->hide_profile_link) { - if ($oid->find()) { - while ($oid->fetch()) { - $links[] = array('href' => $oid->display, - 'text' => _('OpenID'), - 'image' => $this->path("icons/openid-16x16.gif")); + $oid = new User_openid(); + + $oid->user_id = $profile->id; + + if ($oid->find()) { + while ($oid->fetch()) { + $links[] = array('href' => $oid->display, + 'text' => _('OpenID'), + 'image' => $this->path("icons/openid-16x16.gif")); + } } } diff --git a/plugins/OpenID/User_openid_prefs.php b/plugins/OpenID/User_openid_prefs.php new file mode 100644 index 0000000000..74a21f685e --- /dev/null +++ b/plugins/OpenID/User_openid_prefs.php @@ -0,0 +1,100 @@ +. + * + * @category OpenID + * @package StatusNet + * @author Evan Prodromou + * @copyright 2012 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); +} + +/** + * Store preferences for OpenID use in StatusNet + * + * @category OpenID + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * @see DB_DataObject + */ + +class User_openid_prefs extends Managed_DataObject +{ + public $__table = 'user_openid_prefs'; // table name + + public $user_id; // The User with the prefs + public $hide_profile_link; // Hide the link on the profile block? + public $created; // datetime + public $modified; // datetime + + /** + * Get an instance by key + * + * This is a utility method to get a single instance with a given key value. + * + * @param string $k Key to use to lookup (usually 'user_id' for this class) + * @param mixed $v Value to lookup + * + * @return TagSub object found, or null for no hits + * + */ + function staticGet($k, $v=null) + { + return Managed_DataObject::staticGet('User_openid_prefs', $k, $v); + } + + /** + * The One True Thingy that must be defined and declared. + */ + + public static function schemaDef() + { + return array( + 'description' => 'Per-user preferences for OpenID display', + 'fields' => array('user_id' => array('type' => 'integer', + 'not null' => true, + 'description' => 'User whose prefs we are saving'), + 'hide_profile_link' => array('type' => 'int', + 'not null' => true, + 'default' => 0, + 'description' => 'Whether to hide profile links from profile block'), + 'created' => array('type' => 'datetime', + 'not null' => true, + 'description' => 'date this record was created'), + 'modified' => array('type' => 'datetime', + 'not null' => true, + 'description' => 'date this record was modified'), + ), + 'primary key' => array('user_id'), + 'foreign keys' => array('user_openid_prefs_user_id_fkey' => array('user', array('user_id' => 'id')), + ), + 'indexes' => array(), + ); + } +} diff --git a/plugins/OpenID/openidsettings.php b/plugins/OpenID/openidsettings.php index f1a62384b4..0dc4930ce1 100644 --- a/plugins/OpenID/openidsettings.php +++ b/plugins/OpenID/openidsettings.php @@ -222,6 +222,22 @@ class OpenidsettingsAction extends SettingsAction // TRANS: Button text to remove an OpenID trustroot. 'value' => _m('BUTTON','Remove'))); $this->elementEnd('fieldset'); + + $prefs = User_openid_prefs::staticGet('user_id', $user->id); + + $this->elementStart('fieldset'); + $this->element('legend', null, _m('LEGEND','Preferences')); + $this->elementStart('ul', 'form_data'); + $this->checkBox('hide_profile_link', "Hide OpenID links from my profile", !empty($prefs) && $prefs->hide_profile_link); + $this->element('input', array('type' => 'submit', + 'id' => 'settings_openid_prefs_save', + 'name' => 'save_prefs', + 'class' => 'submit', + // TRANS: Button text to save OpenID prefs + 'value' => _m('BUTTON','Save'))); + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + $this->elementEnd('form'); } @@ -258,6 +274,8 @@ class OpenidsettingsAction extends SettingsAction $this->removeOpenid(); } else if($this->arg('remove_trustroots')) { $this->removeTrustroots(); + } else if($this->arg('save_prefs')) { + $this->savePrefs(); } else { // TRANS: Unexpected form validation error. $this->showForm(_m('Something weird happened.')); @@ -326,4 +344,43 @@ class OpenidsettingsAction extends SettingsAction $this->showForm(_m('OpenID removed.'), true); return; } + + /** + * Handles a request to save preferences + * + * Validates input and, if everything is OK, deletes the OpenID. + * Reloads the form with a success or error notification. + * + * @return void + */ + function savePrefs() + { + $cur = common_current_user(); + + if (empty($cur)) { + throw new ClientException(_("Not logged in.")); + } + + $orig = null; + $prefs = User_openid_prefs::staticGet('user_id', $cur->id); + + if (empty($prefs)) { + $prefs = new User_openid_prefs(); + $prefs->user_id = $cur->id; + $prefs->created = common_sql_now(); + } else { + $orig = clone($prefs); + } + + $prefs->hide_profile_link = $this->boolean('hide_profile_link'); + + if (empty($orig)) { + $prefs->insert(); + } else { + $prefs->update($orig); + } + + $this->showForm(_m('OpenID preferences saved.'), true); + return; + } } From 3ad77e8bb2eaea62b440bccec95f1868fa32bf33 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 10 Jul 2012 12:25:19 -0400 Subject: [PATCH 11/11] Squashed commit of the following: commit c2e8966fe76a30ce976973d6d4856cb6bff1cfc9 Author: Evan Prodromou Date: Tue Jul 10 12:20:29 2012 -0400 Do it in ascending date order commit aff18666662e7ba9f23b2d4c30d49347a761cd0a Author: Evan Prodromou Date: Tue Jul 10 12:17:30 2012 -0400 smaller year commit 73c92c081c68cee5019adf1b9e813c7830dd8f87 Author: Evan Prodromou Date: Tue Jul 10 12:16:39 2012 -0400 Smaller role footprint commit a602733dd6f82415706077218f5735b655e47f70 Author: Evan Prodromou Date: Tue Jul 10 12:14:23 2012 -0400 Add the right to view the log commit a5e6cc9791e6ed1ca268b19b6c557ec78bc38e2d Author: Evan Prodromou Date: Tue Jul 10 12:10:15 2012 -0400 Change column name from 'grant' to 'is_grant' since 'grant' is a SQL keyword commit 38fbba009cd7ae379583acdc48480829c40c829d Author: Evan Prodromou Date: Tue Jul 10 12:05:44 2012 -0400 ModLog::getSchema() -> ModLog::schemaDef() commit 970e05d52a4a82630df6962929079c778c118a8b Author: Evan Prodromou Date: Tue Jul 10 12:04:08 2012 -0400 First pass at ModLog plugin --- plugins/ModLog/ModLog.php | 123 ++++++++++++++++++ plugins/ModLog/ModLogPlugin.php | 218 ++++++++++++++++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 plugins/ModLog/ModLog.php create mode 100644 plugins/ModLog/ModLogPlugin.php diff --git a/plugins/ModLog/ModLog.php b/plugins/ModLog/ModLog.php new file mode 100644 index 0000000000..b2c6546838 --- /dev/null +++ b/plugins/ModLog/ModLog.php @@ -0,0 +1,123 @@ +. + * + * @category Moderation + * @package StatusNet + * @author Evan Prodromou + * @copyright 2012 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); +} + +/** + * Class comment here + * + * @category Category here + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * @see DB_DataObject + */ + +class ModLog extends Managed_DataObject +{ + public $__table = 'mod_log'; // table name + + public $id; // UUID + public $profile_id; // profile id + public $moderator_id; // profile id + public $role; // the role + public $grant; // 1 = grant, 0 = revoke + public $created; // datetime + + /** + * 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 TagSub object found, or null for no hits + * + */ + function staticGet($k, $v=null) + { + return Managed_DataObject::staticGet('ModLog', $k, $v); + } + + /** + * Get an instance by compound key + * + * @param array $kv array of key-value mappings + * + * @return TagSub object found, or null for no hits + * + */ + function pkeyGet($kv) + { + return Managed_DataObject::pkeyGet('ModLog', $kv); + } + + /** + * The One True Thingy that must be defined and declared. + */ + public static function schemaDef() + { + return array('description' => 'Log of moderation events', + 'fields' => array( + 'id' => array('type' => 'varchar', + 'length' => 36, + 'not null' => true, + 'description' => 'unique event ID'), + 'profile_id' => array('type' => 'int', + 'not null' => true, + 'description' => 'profile getting the role'), + 'moderator_id' => array('type' => 'int', + 'description' => 'profile granting or revoking the role'), + 'role' => array('type' => 'varchar', + 'length' => 32, + 'not null' => true, + 'description' => 'role granted or revoked'), + 'is_grant' => array('type' => 'int', + 'size' => 'tiny', + 'default' => 1, + 'description' => 'Was this a grant or revocation of a role'), + 'created' => array('type' => 'datetime', + 'not null' => true, + 'description' => 'date this record was created') + ), + 'primary key' => array('id'), + 'foreign keys' => array( + 'mod_log_profile_id_fkey' => array('profile', array('profile_id' => 'id')), + 'mod_log_moderator_id_fkey' => array('user', array('user_id' => 'id')) + ), + 'indexes' => array( + 'mod_log_profile_id_created_idx' => array('profile_id', 'created'), + ), + ); + } +} diff --git a/plugins/ModLog/ModLogPlugin.php b/plugins/ModLog/ModLogPlugin.php new file mode 100644 index 0000000000..459df63e82 --- /dev/null +++ b/plugins/ModLog/ModLogPlugin.php @@ -0,0 +1,218 @@ +. + * + * @category Moderation + * @package StatusNet + * @author Evan Prodromou + * @copyright 2012 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Moderation logging + * + * Shows a history of moderation for this user in the sidebar + * + * @category Moderation + * @package StatusNet + * @author Evan Prodromou + * @copyright 2012 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class ModLogPlugin extends Plugin +{ + const VIEWMODLOG = 'ModLogPlugin::VIEWMODLOG'; + + /** + * Database schema setup + * + * We keep a moderation log table + * + * @see Schema + * @see ColumnDef + * + * @return boolean hook value; true means continue processing, false means stop. + */ + + function onCheckSchema() + { + $schema = Schema::get(); + + $schema->ensureTable('mod_log', ModLog::schemaDef()); + + 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 'ModLog': + include_once $dir . '/'.$cls.'.php'; + return false; + default: + return true; + } + } + + function onEndGrantRole($profile, $role) + { + $modlog = new ModLog(); + + $modlog->id = UUID::gen(); + $modlog->profile_id = $profile->id; + + $cur = common_current_user(); + + if (!empty($cur)) { + $modlog->moderator_id = $cur->id; + } + + $modlog->role = $role; + $modlog->is_grant = 1; + $modlog->created = common_sql_now(); + + $modlog->insert(); + + return true; + } + + function onEndRevokeRole($profile, $role) + { + $modlog = new ModLog(); + + $modlog->id = UUID::gen(); + + $modlog->profile_id = $profile->id; + + $cur = common_current_user(); + + if (!empty($cur)) { + $modlog->moderator_id = $cur->id; + } + + $modlog->role = $role; + $modlog->is_grant = 0; + $modlog->created = common_sql_now(); + + $modlog->insert(); + + return true; + } + + function onEndShowSections($action) + { + if ($action->arg('action') != 'showstream') { + return true; + } + + $cur = common_current_user(); + + if (empty($cur) || !$cur->hasRight(self::VIEWMODLOG)) { + return true; + } + + $profile = $action->profile; + + $ml = new ModLog(); + + $ml->profile_id = $profile->id; + $ml->orderBy("created"); + + $cnt = $ml->find(); + + if ($cnt > 0) { + + $action->elementStart('div', array('id' => 'entity_mod_log', + 'class' => 'section')); + + $action->element('h2', null, _('Moderation')); + + $action->elementStart('table'); + + while ($ml->fetch()) { + $action->elementStart('tr'); + $action->element('td', null, strftime('%y-%m-%d', strtotime($ml->created))); + $action->element('td', null, sprintf(($ml->is_grant) ? _('+%s') : _('-%s'), $ml->role)); + $action->elementStart('td'); + if ($ml->moderator_id) { + $mod = Profile::staticGet('id', $ml->moderator_id); + if (empty($mod)) { + $action->text(_('[unknown]')); + } else { + $action->element('a', array('href' => $mod->profileurl, + 'title' => $mod->fullname), + $mod->nickname); + } + } else { + $action->text(_('[unknown]')); + } + $action->elementEnd('td'); + $action->elementEnd('tr'); + } + + $action->elementEnd('table'); + + $action->elementEnd('div'); + } + } + + function onUserRightsCheck($profile, $right, &$result) { + switch ($right) { + case self::VIEWMODLOG: + $result = ($profile->hasRole(Profile_role::MODERATOR) || $profile->hasRole('modhelper')); + return false; + default: + return true; + } + } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'ModLog', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou', + 'homepage' => 'http://status.net/wiki/Plugin:ModLog', + 'description' => + _m('Show the moderation history for a profile in the sidebar')); + return true; + } +}