Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing

This commit is contained in:
Evan Prodromou 2010-02-06 11:24:12 +01:00
commit 823939ca84
30 changed files with 319 additions and 112 deletions

View File

@ -66,18 +66,21 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction
{ {
parent::handle($args); parent::handle($args);
switch ($this->format) { if (!in_array($this->format, array('xml', 'json'))) {
case 'xml': $this->clientError(_('API method not found.'), $code = 404);
case 'json': return;
$args['id'] = $this->auth_user->id;
$action_obj = new ApiUserShowAction();
if ($action_obj->prepare($args)) {
$action_obj->handle($args);
} }
break;
default: $twitter_user = $this->twitterUserArray($this->auth_user->getProfile(), true);
header('Content-Type: text/html; charset=utf-8');
print 'Authorized'; if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');
$this->showJsonObjects($twitter_user);
$this->endDocument('json');
} }
} }

View File

@ -145,7 +145,7 @@ class ApiGroupJoinAction extends ApiAuthAction
switch($this->format) { switch($this->format) {
case 'xml': case 'xml':
$this->show_single_xml_group($this->group); $this->showSingleXmlGroup($this->group);
break; break;
case 'json': case 'json':
$this->showSingleJsonGroup($this->group); $this->showSingleJsonGroup($this->group);

View File

@ -131,7 +131,7 @@ class ApiGroupLeaveAction extends ApiAuthAction
switch($this->format) { switch($this->format) {
case 'xml': case 'xml':
$this->show_single_xml_group($this->group); $this->showSingleXmlGroup($this->group);
break; break;
case 'json': case 'json':
$this->showSingleJsonGroup($this->group); $this->showSingleJsonGroup($this->group);

View File

@ -186,10 +186,13 @@ class FavoritedAction extends Action
function showContent() function showContent()
{ {
$weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff'));
$cutoff = sprintf("fave.modified > '%s'",
common_sql_date(time() - common_config('popular', 'cutoff')));
$qry = 'SELECT notice.*, '. $qry = 'SELECT notice.*, '.
$weightexpr . ' as weight ' . $weightexpr . ' as weight ' .
'FROM notice JOIN fave ON notice.id = fave.notice_id ' . 'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
"WHERE $cutoff " .
'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source,notice.conversation ' . 'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source,notice.conversation ' .
'ORDER BY weight DESC'; 'ORDER BY weight DESC';

View File

@ -106,7 +106,10 @@ class PublictagcloudAction extends Action
#Add the aggregated columns... #Add the aggregated columns...
$tags->selectAdd('max(notice_id) as last_notice_id'); $tags->selectAdd('max(notice_id) as last_notice_id');
$calc = common_sql_weight('created', common_config('tag', 'dropoff')); $calc = common_sql_weight('created', common_config('tag', 'dropoff'));
$cutoff = sprintf("notice_tag.created > '%s'",
common_sql_date(time() - common_config('tag', 'cutoff')));
$tags->selectAdd($calc . ' as weight'); $tags->selectAdd($calc . ' as weight');
$tags->addWhere($cutoff);
$tags->groupBy('tag'); $tags->groupBy('tag');
$tags->orderBy('weight DESC'); $tags->orderBy('weight DESC');

View File

@ -280,7 +280,7 @@ class RegisterAction extends Action
function nicknameExists($nickname) function nicknameExists($nickname)
{ {
$user = User::staticGet('nickname', $nickname); $user = User::staticGet('nickname', $nickname);
return ($user !== false); return is_object($user);
} }
/** /**
@ -300,7 +300,7 @@ class RegisterAction extends Action
return false; return false;
} }
$user = User::staticGet('email', $email); $user = User::staticGet('email', $email);
return ($user !== false); return is_object($user);
} }
// overrrided to add entry-title class // overrrided to add entry-title class

View File

@ -127,10 +127,10 @@ class UserauthorizationAction extends Action
$location = $params->getLocation(); $location = $params->getLocation();
$avatar = $params->getAvatarURL(); $avatar = $params->getAvatarURL();
$this->elementStart('div', array('class' => 'profile'));
$this->elementStart('div', 'entity_profile vcard'); $this->elementStart('div', 'entity_profile vcard');
$this->elementStart('a', array('href' => $profile, $this->elementStart('dl', 'entity_depiction');
'class' => 'url')); $this->element('dt', null, _('Photo'));
$this->elementStart('dd');
if ($avatar) { if ($avatar) {
$this->element('img', array('src' => $avatar, $this->element('img', array('src' => $avatar,
'class' => 'photo avatar', 'class' => 'photo avatar',
@ -138,11 +138,19 @@ class UserauthorizationAction extends Action
'height' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE,
'alt' => $nickname)); 'alt' => $nickname));
} }
$this->elementEnd('dd');
$this->elementEnd('dl');
$this->elementStart('dl', 'entity_nickname');
$this->element('dt', null, _('Nickname'));
$this->elementStart('dd');
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname'; $hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
$this->elementStart('span', $hasFN); $this->elementStart('a', array('href' => $profile,
'class' => 'url '.$hasFN));
$this->raw($nickname); $this->raw($nickname);
$this->elementEnd('span');
$this->elementEnd('a'); $this->elementEnd('a');
$this->elementEnd('dd');
$this->elementEnd('dl');
if (!is_null($fullname)) { if (!is_null($fullname)) {
$this->elementStart('dl', 'entity_fn'); $this->elementStart('dl', 'entity_fn');
@ -214,7 +222,6 @@ class UserauthorizationAction extends Action
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->elementEnd('div'); $this->elementEnd('div');
$this->elementEnd('div');
} }
function sendAuthorization() function sendAuthorization()

View File

@ -32,6 +32,7 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Inbox extends Memcached_DataObject class Inbox extends Memcached_DataObject
{ {
const BOXCAR = 128; const BOXCAR = 128;
const MAX_NOTICES = 1024;
###START_AUTOCODE ###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */ /* the code below is auto generated do not remove the above tag */
@ -81,7 +82,7 @@ class Inbox extends Memcached_DataObject
$ni->selectAdd(); $ni->selectAdd();
$ni->selectAdd('notice_id'); $ni->selectAdd('notice_id');
$ni->orderBy('notice_id DESC'); $ni->orderBy('notice_id DESC');
$ni->limit(0, 1024); $ni->limit(0, self::MAX_NOTICES);
if ($ni->find()) { if ($ni->find()) {
while($ni->fetch()) { while($ni->fetch()) {
@ -115,9 +116,11 @@ class Inbox extends Memcached_DataObject
$result = $inbox->query(sprintf('UPDATE inbox '. $result = $inbox->query(sprintf('UPDATE inbox '.
'set notice_ids = concat(cast(0x%08x as binary(4)), '. 'set notice_ids = concat(cast(0x%08x as binary(4)), '.
'substr(notice_ids, 1, 4092)) '. 'substr(notice_ids, 1, %d)) '.
'WHERE user_id = %d', 'WHERE user_id = %d',
$notice_id, $user_id)); $notice_id,
4 * (self::MAX_NOTICES - 1),
$user_id));
if ($result) { if ($result) {
self::blow('inbox:user_id:%d', $user_id); self::blow('inbox:user_id:%d', $user_id);
@ -173,4 +176,57 @@ class Inbox extends Memcached_DataObject
return $ids; return $ids;
} }
/**
* Wrapper for Inbox::stream() and Notice::getStreamByIds() returning
* additional items up to the limit if we were short due to deleted
* notices still being listed in the inbox.
*
* The fast path (when no items are deleted) should be just as fast; the
* offset parameter is applied *before* lookups for maximum efficiency.
*
* This means offset-based paging may show duplicates, but similar behavior
* already exists when new notices are posted between page views, so we
* think people will be ok with this until id-based paging is introduced
* to the user interface.
*
* @param int $user_id
* @param int $offset skip past the most recent N notices (after since_id checks)
* @param int $limit
* @param mixed $since_id return only notices after but not including this id
* @param mixed $max_id return only notices up to and including this id
* @param mixed $since obsolete/ignored
* @param mixed $own ignored?
* @return array of Notice objects
*
* @todo consider repacking the inbox when this happens?
*/
function streamNotices($user_id, $offset, $limit, $since_id, $max_id, $since, $own=false)
{
$ids = self::stream($user_id, $offset, self::MAX_NOTICES, $since_id, $max_id, $since, $own);
// Do a bulk lookup for the first $limit items
// Fast path when nothing's deleted.
$firstChunk = array_slice($ids, 0, $limit);
$notices = Notice::getStreamByIds($firstChunk);
$wanted = count($firstChunk); // raw entry count in the inbox up to our $limit
if ($notices->N >= $wanted) {
return $notices;
}
// There were deleted notices, we'll need to look for more.
assert($notices instanceof ArrayWrapper);
$items = $notices->_items;
$remainder = array_slice($ids, $limit);
while (count($items) < $wanted && count($remainder) > 0) {
$notice = Notice::staticGet(array_shift($remainder));
if ($notice) {
$items[] = $notice;
} else {
}
}
return new ArrayWrapper($items);
}
} }

View File

@ -363,7 +363,7 @@ class Memcached_DataObject extends DB_DataObject
$cached[] = clone($inst); $cached[] = clone($inst);
} }
$inst->free(); $inst->free();
$c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry); $c->set($ckey, $cached, Cache::COMPRESSED, $expiry);
return new ArrayWrapper($cached); return new ArrayWrapper($cached);
} }

View File

@ -502,28 +502,22 @@ class User extends Memcached_DataObject
function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$ids = Inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, false); return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, false);
return Notice::getStreamByIds($ids);
} }
function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$ids = Inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, true); return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, true);
return Notice::getStreamByIds($ids);
} }
function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$ids = Inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, false); return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, false);
return Notice::getStreamByIds($ids);
} }
function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{ {
$ids = Inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, true); return Inbox::streamNotices($this->id, $offset, $limit, $since_id, $before_id, $since, true);
return Notice::getStreamByIds($ids);
} }
function blowFavesCache() function blowFavesCache()

View File

@ -353,7 +353,7 @@ notice_id = K
id = 129 id = 129
owner = 129 owner = 129
consumer_key = 130 consumer_key = 130
name = 2 name = 130
description = 2 description = 2
icon = 130 icon = 130
source_url = 2 source_url = 2

View File

@ -214,7 +214,7 @@ create table oauth_application (
id integer auto_increment primary key comment 'unique identifier', id integer auto_increment primary key comment 'unique identifier',
owner integer not null comment 'owner of the application' references profile (id), owner integer not null comment 'owner of the application' references profile (id),
consumer_key varchar(255) not null comment 'application consumer key' references consumer (consumer_key), consumer_key varchar(255) not null comment 'application consumer key' references consumer (consumer_key),
name varchar(255) unique key comment 'name of the application', name varchar(255) not null unique key comment 'name of the application',
description varchar(255) comment 'description of the application', description varchar(255) comment 'description of the application',
icon varchar(255) not null comment 'application icon', icon varchar(255) not null comment 'application icon',
source_url varchar(255) comment 'application homepage - used for source link', source_url varchar(255) comment 'application homepage - used for source link',

View File

@ -47,6 +47,8 @@ class Cache
var $_items = array(); var $_items = array();
static $_inst = null; static $_inst = null;
const COMPRESSED = 1;
/** /**
* Singleton constructor * Singleton constructor
* *
@ -133,7 +135,7 @@ class Cache
* *
* @param string $key The key to use for lookups * @param string $key The key to use for lookups
* @param string $value The value to store * @param string $value The value to store
* @param integer $flag Flags to use, mostly ignored * @param integer $flag Flags to use, may include Cache::COMPRESSED
* @param integer $expiry Expiry value, mostly ignored * @param integer $expiry Expiry value, mostly ignored
* *
* @return boolean success flag * @return boolean success flag

View File

@ -144,9 +144,11 @@ $default =
'invite' => 'invite' =>
array('enabled' => true), array('enabled' => true),
'tag' => 'tag' =>
array('dropoff' => 864000.0), array('dropoff' => 864000.0, # controls weighting based on age
'cutoff' => 86400 * 90), # only look at notices posted in last 90 days
'popular' => 'popular' =>
array('dropoff' => 864000.0), array('dropoff' => 864000.0, # controls weighting based on age
'cutoff' => 86400 * 90), # only look at notices favorited in last 90 days
'daemon' => 'daemon' =>
array('piddir' => '/var/run', array('piddir' => '/var/run',
'user' => false, 'user' => false,

View File

@ -59,6 +59,7 @@ class GroupTagCloudSection extends TagCloudSection
function getTags() function getTags()
{ {
$weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
// @fixme should we use the cutoff too? Doesn't help with indexing per-group.
$names = $this->group->getAliases(); $names = $this->group->getAliases();

View File

@ -65,7 +65,7 @@ class StatusNetOAuthDataStore extends OAuthDataStore
{ {
$n = new Nonce(); $n = new Nonce();
$n->consumer_key = $consumer->key; $n->consumer_key = $consumer->key;
$n->ts = $timestamp; $n->ts = common_sql_date($timestamp);
$n->nonce = $nonce; $n->nonce = $nonce;
if ($n->find(true)) { if ($n->find(true)) {
return true; return true;
@ -362,7 +362,6 @@ class StatusNetOAuthDataStore extends OAuthDataStore
array('is_local' => Notice::REMOTE_OMB, array('is_local' => Notice::REMOTE_OMB,
'uri' => $omb_notice->getIdentifierURI())); 'uri' => $omb_notice->getIdentifierURI()));
} }
/** /**

View File

@ -59,6 +59,7 @@ class PersonalTagCloudSection extends TagCloudSection
function getTags() function getTags()
{ {
$weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
// @fixme should we use the cutoff too? Doesn't help with indexing per-user.
$qry = 'SELECT notice_tag.tag, '. $qry = 'SELECT notice_tag.tag, '.
$weightexpr . ' as weight ' . $weightexpr . ' as weight ' .

View File

@ -59,12 +59,15 @@ class PopularNoticeSection extends NoticeSection
} }
} }
$weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff'));
$cutoff = sprintf("fave.modified > '%s'",
common_sql_date(time() - common_config('popular', 'cutoff')));
$qry = "SELECT notice.*, $weightexpr as weight "; $qry = "SELECT notice.*, $weightexpr as weight ";
if(isset($tag)) { if(isset($tag)) {
$qry .= 'FROM notice_tag, notice JOIN fave ON notice.id = fave.notice_id ' . $qry .= 'FROM notice_tag, notice JOIN fave ON notice.id = fave.notice_id ' .
"WHERE notice.id = notice_tag.notice_id and '$tag' = notice_tag.tag"; "WHERE $cutoff and notice.id = notice_tag.notice_id and '$tag' = notice_tag.tag";
} else { } else {
$qry .= 'FROM notice JOIN fave ON notice.id = fave.notice_id'; $qry .= 'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
"WHERE $cutoff";
} }
$qry .= ' GROUP BY notice.id,notice.profile_id,notice.content,notice.uri,' . $qry .= ' GROUP BY notice.id,notice.profile_id,notice.content,notice.uri,' .
'notice.rendered,notice.url,notice.created,notice.modified,' . 'notice.rendered,notice.url,notice.created,notice.modified,' .

View File

@ -102,7 +102,7 @@ class MemcachePlugin extends Plugin
* *
* @param string &$key in; Key to use for lookups * @param string &$key in; Key to use for lookups
* @param mixed &$value in; Value to associate * @param mixed &$value in; Value to associate
* @param integer &$flag in; Flag (passed through to Memcache) * @param integer &$flag in; Flag empty or Cache::COMPRESSED
* @param integer &$expiry in; Expiry (passed through to Memcache) * @param integer &$expiry in; Expiry (passed through to Memcache)
* @param boolean &$success out; Whether the set was successful * @param boolean &$success out; Whether the set was successful
* *
@ -115,7 +115,7 @@ class MemcachePlugin extends Plugin
if ($expiry === null) { if ($expiry === null) {
$expiry = $this->defaultExpiry; $expiry = $this->defaultExpiry;
} }
$success = $this->_conn->set($key, $value, $flag, $expiry); $success = $this->_conn->set($key, $value, $this->flag(intval($flag)), $expiry);
Event::handle('EndCacheSet', array($key, $value, $flag, Event::handle('EndCacheSet', array($key, $value, $flag,
$expiry)); $expiry));
return false; return false;
@ -197,6 +197,20 @@ class MemcachePlugin extends Plugin
} }
} }
/**
* Translate general flags to Memcached-specific flags
* @param int $flag
* @return int
*/
protected function flag($flag)
{
$out = 0;
if ($flag & Cache::COMPRESSED == Cache::COMPRESSED) {
$out |= MEMCACHE_COMPRESSED;
}
return $out;
}
function onPluginVersion(&$versions) function onPluginVersion(&$versions)
{ {
$versions[] = array('name' => 'Memcache', $versions[] = array('name' => 'Memcache',

View File

@ -240,6 +240,8 @@ class MobileProfilePlugin extends WAP20Plugin
return true; return true;
} }
$action->cssLink('css/display.css');
if (file_exists(Theme::file('css/mp-screen.css'))) { if (file_exists(Theme::file('css/mp-screen.css'))) {
$action->cssLink('css/mp-screen.css', null, 'screen'); $action->cssLink('css/mp-screen.css', null, 'screen');
} else { } else {
@ -256,6 +258,14 @@ class MobileProfilePlugin extends WAP20Plugin
} }
function onStartShowUAStyles($action) {
if (!$this->serveMobile) {
return true;
}
return false;
}
function onStartShowHeader($action) function onStartShowHeader($action)
{ {
if (!$this->serveMobile) { if (!$this->serveMobile) {

View File

@ -7,9 +7,6 @@
* @link http://status.net/ * @link http://status.net/
*/ */
@import url(../../theme/base/css/display.css);
@import url(../../theme/identica/css/display.css);
#wrap { #wrap {
min-width:0; min-width:0;
max-width:100%; max-width:100%;

View File

@ -2,7 +2,7 @@
<?php <?php
/** /**
* StatusNet - the distributed open-source microblogging tool * StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc. * Copyright (C) 2008-2010, StatusNet, Inc.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
@ -262,7 +262,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon
$notice->is_local = Notice::GATEWAY; $notice->is_local = Notice::GATEWAY;
if (Event::handle('StartNoticeSave', array(&$notice))) { if (Event::handle('StartNoticeSave', array(&$notice))) {
$id = $notice->insert(); $notice->insert();
Event::handle('EndNoticeSave', array($notice)); Event::handle('EndNoticeSave', array($notice));
} }
@ -270,17 +270,41 @@ class TwitterStatusFetcher extends ParallelizingDaemon
Inbox::insertNotice($flink->user_id, $notice->id); Inbox::insertNotice($flink->user_id, $notice->id);
$notice->blowCaches(); $notice->blowOnInsert();
return $notice; return $notice;
} }
/**
* Look up a Profile by profileurl field. Profile::staticGet() was
* not working consistently.
*
* @param string $url the profile url
*
* @return mixed the first profile with that url, or null
*/
function getProfileByUrl($nickname, $profileurl)
{
$profile = new Profile();
$profile->nickname = $nickname;
$profile->profileurl = $profileurl;
$profile->limit(1);
if ($profile->find()) {
$profile->fetch();
return $profile;
}
return null;
}
function ensureProfile($user) function ensureProfile($user)
{ {
// check to see if there's already a profile for this user // check to see if there's already a profile for this user
$profileurl = 'http://twitter.com/' . $user->screen_name; $profileurl = 'http://twitter.com/' . $user->screen_name;
$profile = Profile::staticGet('profileurl', $profileurl); $profile = $this->getProfileByUrl($user->screen_name, $profileurl);
if (!empty($profile)) { if (!empty($profile)) {
common_debug($this->name() . common_debug($this->name() .
@ -292,6 +316,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon
return $profile->id; return $profile->id;
} else { } else {
common_debug($this->name() . ' - Adding profile and remote profile ' . common_debug($this->name() . ' - Adding profile and remote profile ' .
"for Twitter user: $profileurl."); "for Twitter user: $profileurl.");
@ -306,7 +331,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon
$profile->profileurl = $profileurl; $profile->profileurl = $profileurl;
$profile->created = common_sql_now(); $profile->created = common_sql_now();
try {
$id = $profile->insert(); $id = $profile->insert();
} catch(Exception $e) {
common_log(LOG_WARNING, $this->name . ' Couldn\'t insert profile - ' . $e->getMessage());
}
if (empty($id)) { if (empty($id)) {
common_log_db_error($profile, 'INSERT', __FILE__); common_log_db_error($profile, 'INSERT', __FILE__);
@ -326,7 +355,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon
$remote_pro->uri = $profileurl; $remote_pro->uri = $profileurl;
$remote_pro->created = common_sql_now(); $remote_pro->created = common_sql_now();
try {
$rid = $remote_pro->insert(); $rid = $remote_pro->insert();
} catch (Exception $e) {
common_log(LOG_WARNING, $this->name() . ' Couldn\'t save remote profile - ' . $e->getMessage());
}
if (empty($rid)) { if (empty($rid)) {
common_log_db_error($profile, 'INSERT', __FILE__); common_log_db_error($profile, 'INSERT', __FILE__);
@ -446,7 +479,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon
if ($this->fetchAvatar($url, $filename)) { if ($this->fetchAvatar($url, $filename)) {
$this->newAvatar($id, $size, $mediatype, $filename); $this->newAvatar($id, $size, $mediatype, $filename);
} else { } else {
common_log(LOG_WARNING, $this->id() . common_log(LOG_WARNING, $id() .
" - Problem fetching Avatar: $url"); " - Problem fetching Avatar: $url");
} }
} }
@ -507,7 +540,11 @@ class TwitterStatusFetcher extends ParallelizingDaemon
$avatar->created = common_sql_now(); $avatar->created = common_sql_now();
try {
$id = $avatar->insert(); $id = $avatar->insert();
} catch (Exception $e) {
common_log(LOG_WARNING, $this->name() . ' Couldn\'t insert avatar - ' . $e->getMessage());
}
if (empty($id)) { if (empty($id)) {
common_log_db_error($avatar, 'INSERT', __FILE__); common_log_db_error($avatar, 'INSERT', __FILE__);

View File

@ -26,38 +26,6 @@ define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1
require_once INSTALLDIR . '/plugins/TwitterBridge/twitterbasicauthclient.php'; require_once INSTALLDIR . '/plugins/TwitterBridge/twitterbasicauthclient.php';
require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php';
function updateTwitter_user($twitter_id, $screen_name)
{
$uri = 'http://twitter.com/' . $screen_name;
$fuser = new Foreign_user();
$fuser->query('BEGIN');
// Dropping down to SQL because regular DB_DataObject udpate stuff doesn't seem
// to work so good with tables that have multiple column primary keys
// Any time we update the uri for a forein user we have to make sure there
// are no dupe entries first -- unique constraint on the uri column
$qry = 'UPDATE foreign_user set uri = \'\' WHERE uri = ';
$qry .= '\'' . $uri . '\'' . ' AND service = ' . TWITTER_SERVICE;
$fuser->query($qry);
// Update the user
$qry = 'UPDATE foreign_user SET nickname = ';
$qry .= '\'' . $screen_name . '\'' . ', uri = \'' . $uri . '\' ';
$qry .= 'WHERE id = ' . $twitter_id . ' AND service = ' . TWITTER_SERVICE;
$fuser->query('COMMIT');
$fuser->free();
unset($fuser);
return true;
}
function add_twitter_user($twitter_id, $screen_name) function add_twitter_user($twitter_id, $screen_name)
{ {
@ -105,7 +73,6 @@ function add_twitter_user($twitter_id, $screen_name)
// Creates or Updates a Twitter user // Creates or Updates a Twitter user
function save_twitter_user($twitter_id, $screen_name) function save_twitter_user($twitter_id, $screen_name)
{ {
// Check to see whether the Twitter user is already in the system, // Check to see whether the Twitter user is already in the system,
// and update its screen name and uri if so. // and update its screen name and uri if so.
@ -115,25 +82,20 @@ function save_twitter_user($twitter_id, $screen_name)
$result = true; $result = true;
// Only update if Twitter screen name has changed // Delete old record if Twitter user changed screen name
if ($fuser->nickname != $screen_name) { if ($fuser->nickname != $screen_name) {
$result = updateTwitter_user($twitter_id, $screen_name); $oldname = $fuser->nickname;
$fuser->delete();
common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' . common_log(LOG_INFO, sprintf('Twitter bridge - Updated nickname (and URI) ' .
"$fuser->id to $screen_name, was $fuser->nickname"); 'for Twitter user %1$d - %2$s, was %3$s.',
$fuser->id,
$screen_name,
$oldname));
} }
return $result;
} else {
return add_twitter_user($twitter_id, $screen_name); return add_twitter_user($twitter_id, $screen_name);
} }
$fuser->free();
unset($fuser);
return true;
} }
function is_twitter_bound($notice, $flink) { function is_twitter_bound($notice, $flink) {

View File

@ -219,7 +219,7 @@ class TwitterauthorizationAction extends Action
$user = common_current_user(); $user = common_current_user();
$this->saveForeignLink($user->id, $twitter_user->id, $atok); $this->saveForeignLink($user->id, $twitter_user->id, $atok);
save_twitter_user($twitter_user->id, $twitter_user->name); save_twitter_user($twitter_user->id, $twitter_user->screen_name);
} else { } else {

View File

@ -0,0 +1,99 @@
#!/usr/bin/env php
<?php
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2008, 2009, 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 <http://www.gnu.org/licenses/>.
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
$shortoptions = 'i:n:a';
$longoptions = array('id=', 'nickname=', 'all');
$helptext = <<<END_OF_UPDATEPROFILEURL_HELP
updateprofileurl.php [options]
update the URLs of all avatars in the system
-i --id ID of user to update
-n --nickname nickname of the user to update
-a --all update all
END_OF_UPDATEPROFILEURL_HELP;
require_once INSTALLDIR.'/scripts/commandline.inc';
try {
$user = null;
if (have_option('i', 'id')) {
$id = get_option_value('i', 'id');
$user = User::staticGet('id', $id);
if (empty($user)) {
throw new Exception("Can't find user with id '$id'.");
}
updateProfileURL($user);
} else if (have_option('n', 'nickname')) {
$nickname = get_option_value('n', 'nickname');
$user = User::staticGet('nickname', $nickname);
if (empty($user)) {
throw new Exception("Can't find user with nickname '$nickname'");
}
updateProfileURL($user);
} else if (have_option('a', 'all')) {
$user = new User();
if ($user->find()) {
while ($user->fetch()) {
updateProfileURL($user);
}
}
} else {
show_help();
exit(1);
}
} catch (Exception $e) {
print $e->getMessage()."\n";
exit(1);
}
function updateProfileURL($user)
{
$profile = $user->getProfile();
if (empty($profile)) {
throw new Exception("Can't find profile for user $user->nickname ($user->id)");
}
$orig = clone($profile);
$profile->profileurl = common_profile_url($user->nickname);
if (!have_option('q', 'quiet')) {
print "Updating profile url for $user->nickname ($user->id) ".
"from $orig->profileurl to $profile->profileurl...";
}
$result = $profile->update($orig);
if (!$result) {
print "FAIL.\n";
common_log_db_error($profile, 'UPDATE', __FILE__);
throw new Exception("Can't update profile for user $user->nickname ($user->id)");
}
common_broadcast_profile($profile);
print "OK.\n";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 B

View File

@ -192,7 +192,8 @@ button.minimize,
.form_reset_key input.submit, .form_reset_key input.submit,
.entity_clear input.submit, .entity_clear input.submit,
.entity_flag input.submit, .entity_flag input.submit,
.entity_flag p { .entity_flag p,
.entity_subscribe input.submit {
background-image:url(../../base/images/icons/icons-01.gif); background-image:url(../../base/images/icons/icons-01.gif);
background-repeat:no-repeat; background-repeat:no-repeat;
background-color:transparent; background-color:transparent;
@ -348,6 +349,12 @@ background-position: 5px -2039px;
.entity_flag p { .entity_flag p {
background-position: 5px -2105px; background-position: 5px -2105px;
} }
.entity_subscribe input.accept {
background-position: 5px -2171px;
}
.entity_subscribe input.reject {
background-position: 5px -2237px;
}
/* NOTICES */ /* NOTICES */
.notice .attachment { .notice .attachment {

View File

@ -192,7 +192,8 @@ button.minimize,
.form_reset_key input.submit, .form_reset_key input.submit,
.entity_clear input.submit, .entity_clear input.submit,
.entity_flag input.submit, .entity_flag input.submit,
.entity_flag p { .entity_flag p,
.entity_subscribe input.submit {
background-image:url(../../base/images/icons/icons-01.gif); background-image:url(../../base/images/icons/icons-01.gif);
background-repeat:no-repeat; background-repeat:no-repeat;
background-color:transparent; background-color:transparent;
@ -347,6 +348,12 @@ background-position: 5px -2039px;
.entity_flag p { .entity_flag p {
background-position: 5px -2105px; background-position: 5px -2105px;
} }
.entity_subscribe input.accept {
background-position: 5px -2171px;
}
.entity_subscribe input.reject {
background-position: 5px -2237px;
}
/* NOTICES */ /* NOTICES */
.notice .attachment { .notice .attachment {