Merge branch 'master' of gitorious.org:statusnet/mainline

This commit is contained in:
Evan Prodromou 2012-07-28 13:59:40 -04:00
commit 330041e8bf
17 changed files with 685 additions and 4 deletions

View File

@ -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

View File

@ -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();

View File

@ -86,4 +86,9 @@ class DefaultProfileBlock extends AccountProfileBlock
{
return null;
}
function otherProfiles()
{
return array();
}
}

View File

@ -85,6 +85,11 @@ class GroupProfileBlock extends ProfileBlock
return $this->group->description;
}
function otherProfiles()
{
return array();
}
function showActions()
{
$cur = common_current_user();

View File

@ -61,6 +61,7 @@ abstract class ProfileBlock extends Widget
$this->showName();
$this->showLocation();
$this->showHomepage();
$this->showOtherProfiles();
$this->showDescription();
$this->showTags();
}
@ -133,6 +134,33 @@ 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',
'title' => $otherProfile['text']));
$this->out->element('img',
array('src' => $otherProfile['image'],
'class' => 'profile_block_otherprofile_icon'));
$this->out->elementEnd('a');
$this->out->elementEnd('li');
}
$this->out->elementEnd('ul');
}
}
function avatarSize()
{
return AVATAR_PROFILE_SIZE;

View File

@ -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:%s", $id));
$c = Cache::instance();
if ($c) {
$obj = $c->get($key);
if ($obj) {
return $obj;
}
}
$url = sprintf("https://graph.facebook.com/%s", $id);
$client = new HTTPClient();
$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
*

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

123
plugins/ModLog/ModLog.php Normal file
View File

@ -0,0 +1,123 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* ModLog.php -- data object to store moderation logs
*
* PHP version 5
*
* 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 <http://www.gnu.org/licenses/>.
*
* @category Moderation
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @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 <evan@status.net>
* @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'),
),
);
}
}

View File

@ -0,0 +1,218 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* ModLogPlugin.php
*
* PHP version 5
*
* 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 <http://www.gnu.org/licenses/>.
*
* @category Moderation
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @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 <evan@status.net>
* @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;
}
}

View File

@ -146,6 +146,8 @@ class OStatusGroupAction extends OStatusSubAction
try {
$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;

View File

@ -20,7 +20,7 @@
* @category Plugin
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Craig Andrews <candrews@integralblue.com>
* @author Craig Andrews <candrews@integralblue.com>
* @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
@ -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',
@ -814,4 +815,35 @@ 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)
{
$prefs = User_openid_prefs::staticGet('user_id', $profile->id);
if (empty($prefs) || !$prefs->hide_profile_link) {
$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;
}
}

View File

@ -0,0 +1,100 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* User_openid_prefs.php
*
* PHP version 5
*
* 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 <http://www.gnu.org/licenses/>.
*
* @category OpenID
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @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 <evan@status.net>
* @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(),
);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

View File

@ -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;
}
}

View File

@ -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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

@ -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*/