Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
This commit is contained in:
commit
823939ca84
@ -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)) {
|
$twitter_user = $this->twitterUserArray($this->auth_user->getProfile(), true);
|
||||||
$action_obj->handle($args);
|
|
||||||
}
|
if ($this->format == 'xml') {
|
||||||
break;
|
$this->initDocument('xml');
|
||||||
default:
|
$this->showTwitterXmlUser($twitter_user);
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
$this->endDocument('xml');
|
||||||
print 'Authorized';
|
} elseif ($this->format == 'json') {
|
||||||
|
$this->initDocument('json');
|
||||||
|
$this->showJsonObjects($twitter_user);
|
||||||
|
$this->endDocument('json');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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';
|
||||||
|
|
||||||
|
@ -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');
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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()));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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 ' .
|
||||||
|
@ -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,' .
|
||||||
|
@ -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',
|
||||||
|
@ -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) {
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
/** theme: mobile profile screen
|
/** theme: mobile profile screen
|
||||||
*
|
*
|
||||||
* @package StatusNet
|
* @package StatusNet
|
||||||
* @author Sarven Capadisli <csarven@status.net>
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
* @copyright 2009 StatusNet, Inc.
|
* @copyright 2009 StatusNet, Inc.
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @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%;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
$id = $profile->insert();
|
try {
|
||||||
|
$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();
|
||||||
|
|
||||||
$rid = $remote_pro->insert();
|
try {
|
||||||
|
$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();
|
||||||
|
|
||||||
$id = $avatar->insert();
|
try {
|
||||||
|
$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__);
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
99
scripts/updateprofileurl.php
Normal file
99
scripts/updateprofileurl.php
Normal 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 |
BIN
theme/base/images/icons/twotone/green/against.gif
Normal file
BIN
theme/base/images/icons/twotone/green/against.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 B |
BIN
theme/base/images/icons/twotone/green/checkmark.gif
Normal file
BIN
theme/base/images/icons/twotone/green/checkmark.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 B |
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user