gnu-social/classes/User.php

1000 lines
30 KiB
PHP
Raw Normal View History

<?php
/*
2009-08-26 07:14:12 +09:00
* StatusNet - the 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/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
2009-03-29 06:42:45 +09:00
exit(1);
}
/**
* Table Definition for user
*/
2009-03-29 06:42:45 +09:00
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
require_once 'Validate.php';
class User extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'user'; // table name
public $id; // int(4) primary_key not_null
public $nickname; // varchar(64) unique_key
public $password; // varchar(255)
public $email; // varchar(255) unique_key
public $incomingemail; // varchar(255) unique_key
public $emailnotifysub; // tinyint(1) default_1
public $emailnotifyfav; // tinyint(1) default_1
public $emailnotifynudge; // tinyint(1) default_1
public $emailnotifymsg; // tinyint(1) default_1
2009-02-17 08:24:43 +09:00
public $emailnotifyattn; // tinyint(1) default_1
public $emailmicroid; // tinyint(1) default_1
public $language; // varchar(50)
public $timezone; // varchar(50)
public $emailpost; // tinyint(1) default_1
public $jabber; // varchar(255) unique_key
public $jabbernotify; // tinyint(1)
public $jabberreplies; // tinyint(1)
public $jabbermicroid; // tinyint(1) default_1
public $updatefrompresence; // tinyint(1)
public $sms; // varchar(64) unique_key
public $carrier; // int(4)
public $smsnotify; // tinyint(1)
public $smsreplies; // tinyint(1)
public $smsemail; // varchar(255)
public $uri; // varchar(255) unique_key
public $autosubscribe; // tinyint(1)
public $urlshorteningservice; // varchar(50) default_ur1.ca
public $inboxed; // tinyint(1)
public $design_id; // int(4)
public $viewdesigns; // tinyint(1) default_1
public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* Static get */
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('User',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
function getProfile()
{
return Profile::staticGet('id', $this->id);
}
function isSubscribed($other)
{
assert(!is_null($other));
2009-03-29 06:42:45 +09:00
// XXX: cache results of this query
$sub = Subscription::pkeyGet(array('subscriber' => $this->id,
'subscribed' => $other->id));
return (is_null($sub)) ? false : true;
}
// 'update' won't write key columns, so we have to do it ourselves.
function updateKeys(&$orig)
{
$parts = array();
foreach (array('nickname', 'email', 'jabber', 'incomingemail', 'sms', 'carrier', 'smsemail', 'language', 'timezone') as $k) {
if (strcmp($this->$k, $orig->$k) != 0) {
$parts[] = $k . ' = ' . $this->_quote($this->$k);
}
}
if (count($parts) == 0) {
2009-03-29 06:42:45 +09:00
// No changes
return true;
}
$toupdate = implode(', ', $parts);
$table = common_database_tablename($this->tableName());
$qry = 'UPDATE ' . $table . ' SET ' . $toupdate .
' WHERE id = ' . $this->id;
$orig->decache();
$result = $this->query($qry);
if ($result) {
$this->encache();
}
return $result;
}
static function allowed_nickname($nickname)
{
2009-03-29 06:42:45 +09:00
// XXX: should already be validated for size, content, etc.
$blacklist = common_config('nickname', 'blacklist');
//all directory and file names should be blacklisted
$d = dir(INSTALLDIR);
while (false !== ($entry = $d->read())) {
$blacklist[]=$entry;
}
$d->close();
//all top level names in the router should be blacklisted
$router = Router::get();
foreach(array_keys($router->m->getPaths()) as $path){
if(preg_match('/^\/(.*?)[\/\?]/',$path,$matches)){
$blacklist[]=$matches[1];
}
}
return !in_array($nickname, $blacklist);
}
function getCurrentNotice($dt=null)
{
$profile = $this->getProfile();
if (!$profile) {
return null;
}
return $profile->getCurrentNotice($dt);
}
function getCarrier()
{
return Sms_carrier::staticGet('id', $this->carrier);
}
function subscribeTo($other)
{
$sub = new Subscription();
$sub->subscriber = $this->id;
$sub->subscribed = $other->id;
2009-03-29 06:42:45 +09:00
$sub->created = common_sql_now(); // current time
if (!$sub->insert()) {
return false;
}
return true;
}
function hasBlocked($other)
{
$block = Profile_block::get($this->id, $other->id);
if (is_null($block)) {
$result = false;
} else {
$result = true;
$block->free();
}
return $result;
}
/**
* Register a new user account and profile and set up default subscriptions.
* If a new-user welcome message is configured, this will be sent.
*
* @param array $fields associative array of optional properties
* string 'bio'
* string 'email'
* bool 'email_confirmed' pass true to mark email as pre-confirmed
* string 'fullname'
* string 'homepage'
* string 'location' informal string description of geolocation
* float 'lat' decimal latitude for geolocation
* float 'lon' decimal longitude for geolocation
* int 'location_id' geoname identifier
* int 'location_ns' geoname namespace to interpret location_id
* string 'nickname' REQUIRED
* string 'password' (may be missing for eg OpenID registrations)
* string 'code' invite code
* ?string 'uri' permalink to notice; defaults to local notice URL
* @return mixed User object or false on failure
*/
static function register($fields) {
2009-03-29 06:42:45 +09:00
// MAGICALLY put fields into current scope
extract($fields);
$profile = new Profile();
$profile->query('BEGIN');
if(!empty($email))
{
$email = common_canonical_email($email);
}
$nickname = common_canonical_nickname($nickname);
$profile->nickname = $nickname;
if(! User::allowed_nickname($nickname)){
common_log(LOG_WARNING, sprintf("Attempted to register a nickname that is not allowed: %s", $profile->nickname),
__FILE__);
}
$profile->profileurl = common_profile_url($nickname);
if (!empty($fullname)) {
$profile->fullname = $fullname;
}
if (!empty($homepage)) {
$profile->homepage = $homepage;
}
if (!empty($bio)) {
$profile->bio = $bio;
}
if (!empty($location)) {
$profile->location = $location;
2009-10-24 00:46:44 +09:00
$loc = Location::fromName($location);
if (!empty($loc)) {
$profile->lat = $loc->lat;
$profile->lon = $loc->lon;
$profile->location_id = $loc->location_id;
$profile->location_ns = $loc->location_ns;
}
}
$profile->created = common_sql_now();
$id = $profile->insert();
if (empty($id)) {
common_log_db_error($profile, 'INSERT', __FILE__);
return false;
}
$user = new User();
$user->id = $id;
$user->nickname = $nickname;
2009-03-29 06:42:45 +09:00
if (!empty($password)) { // may not have a password for OpenID users
$user->password = common_munge_password($password, $id);
}
2009-03-29 06:42:45 +09:00
// Users who respond to invite email have proven their ownership of that address
if (!empty($code)) {
$invite = Invitation::staticGet($code);
if ($invite && $invite->address && $invite->address_type == 'email' && $invite->address == $email) {
$user->email = $invite->address;
}
}
if(isset($email_confirmed) && $email_confirmed) {
$user->email = $email;
}
2009-10-14 06:38:27 +09:00
// This flag is ignored but still set to 1
2009-10-14 06:38:27 +09:00
$user->inboxed = 1;
$user->created = common_sql_now();
$user->uri = common_user_uri($user);
$result = $user->insert();
if (!$result) {
common_log_db_error($user, 'INSERT', __FILE__);
return false;
}
2009-03-29 06:42:45 +09:00
// Everyone is subscribed to themself
$subscription = new Subscription();
$subscription->subscriber = $user->id;
$subscription->subscribed = $user->id;
$subscription->created = $user->created;
$result = $subscription->insert();
if (!$result) {
common_log_db_error($subscription, 'INSERT', __FILE__);
return false;
}
if (!empty($email) && !$user->email) {
$confirm = new Confirm_address();
$confirm->code = common_confirmation_code(128);
$confirm->user_id = $user->id;
$confirm->address = $email;
$confirm->address_type = 'email';
$result = $confirm->insert();
if (!$result) {
common_log_db_error($confirm, 'INSERT', __FILE__);
return false;
}
}
if (!empty($code) && $user->email) {
$user->emailChanged();
}
// Default system subscription
$defnick = common_config('newuser', 'default');
if (!empty($defnick)) {
$defuser = User::staticGet('nickname', $defnick);
if (empty($defuser)) {
common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
__FILE__);
} else {
$defsub = new Subscription();
$defsub->subscriber = $user->id;
$defsub->subscribed = $defuser->id;
$defsub->created = $user->created;
$result = $defsub->insert();
if (!$result) {
common_log_db_error($defsub, 'INSERT', __FILE__);
return false;
}
}
}
$profile->query('COMMIT');
2009-12-16 07:49:53 +09:00
if (!empty($email) && !$user->email) {
mail_confirm_address($user, $confirm->code, $profile->nickname, $email);
}
// Welcome message
$welcome = common_config('newuser', 'welcome');
if (!empty($welcome)) {
$welcomeuser = User::staticGet('nickname', $welcome);
if (empty($welcomeuser)) {
common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick),
__FILE__);
} else {
$notice = Notice::saveNew($welcomeuser->id,
sprintf(_('Welcome to %1$s, @%2$s!'),
common_config('site', 'name'),
$user->nickname),
'system');
common_broadcast_notice($notice);
}
}
return $user;
}
2009-03-29 06:42:45 +09:00
// Things we do when the email changes
function emailChanged()
{
$invites = new Invitation();
$invites->address = $this->email;
$invites->address_type = 'email';
if ($invites->find()) {
while ($invites->fetch()) {
$other = User::staticGet($invites->user_id);
subs_subscribe_to($other, $this);
}
}
}
function hasFave($notice)
{
$cache = common_memcache();
2009-03-29 06:42:45 +09:00
// XXX: Kind of a hack.
2009-05-02 04:01:28 +09:00
if ($cache) {
2009-03-29 06:42:45 +09:00
// This is the stream of favorite notices, in rev chron
// order. This forces it into cache.
2009-05-02 04:01:28 +09:00
$ids = Fave::stream($this->id, 0, NOTICE_CACHE_WINDOW);
// If it's in the list, then it's a fave
if (in_array($notice->id, $ids)) {
return true;
}
2009-05-02 04:01:28 +09:00
2009-03-29 06:42:45 +09:00
// If we're not past the end of the cache window,
// then the cache has all available faves, so this one
// is not a fave.
2009-05-02 04:01:28 +09:00
if (count($ids) < NOTICE_CACHE_WINDOW) {
return false;
}
2009-05-02 04:01:28 +09:00
// Otherwise, cache doesn't have all faves;
2009-03-29 06:42:45 +09:00
// fall through to the default
}
2009-05-02 04:01:28 +09:00
$fave = Fave::pkeyGet(array('user_id' => $this->id,
'notice_id' => $notice->id));
return ((is_null($fave)) ? false : true);
}
2009-03-29 06:42:45 +09:00
function mutuallySubscribed($other)
{
return $this->isSubscribed($other) &&
$other->isSubscribed($this);
}
2009-03-29 06:42:45 +09:00
function mutuallySubscribedUsers()
{
// 3-way join; probably should get cached
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$qry = "SELECT $UT.* " .
"FROM subscription sub1 JOIN $UT ON sub1.subscribed = $UT.id " .
"JOIN subscription sub2 ON $UT.id = sub2.subscriber " .
'WHERE sub1.subscriber = %d and sub2.subscribed = %d ' .
"ORDER BY $UT.nickname";
$user = new User();
$user->query(sprintf($qry, $this->id, $this->id));
return $user;
}
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
2009-04-30 09:45:33 +09:00
$ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since);
return Notice::getStreamByIds($ids);
}
function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) {
$profile = $this->getProfile();
if (!$profile) {
return null;
} else {
return $profile->getTaggedNotices($tag, $offset, $limit, $since_id, $before_id, $since);
}
}
2009-03-29 06:42:45 +09:00
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
$profile = $this->getProfile();
if (!$profile) {
return null;
} else {
return $profile->getNotices($offset, $limit, $since_id, $before_id, $since);
}
}
function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE, $own=false)
2009-03-29 06:42:45 +09:00
{
$ids = Fave::stream($this->id, $offset, $limit, $own);
2009-05-02 04:01:28 +09:00
return Notice::getStreamByIds($ids);
}
2009-03-29 06:42:45 +09:00
function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
2009-10-14 06:38:27 +09:00
$ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, false);
2009-10-14 06:38:27 +09:00
return Notice::getStreamByIds($ids);
}
function noticeInbox($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
2009-10-14 06:38:27 +09:00
$ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since, true);
2009-10-14 06:38:27 +09:00
return Notice::getStreamByIds($ids);
}
function friendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
$ids = Notice::stream(array($this, '_friendsTimelineDirect'),
array(false),
'user:friends_timeline:'.$this->id,
$offset, $limit, $since_id, $before_id, $since);
return Notice::getStreamByIds($ids);
}
function ownFriendsTimeline($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
$ids = Notice::stream(array($this, '_friendsTimelineDirect'),
array(true),
'user:friends_timeline_own:'.$this->id,
$offset, $limit, $since_id, $before_id, $since);
return Notice::getStreamByIds($ids);
}
function _friendsTimelineDirect($own, $offset, $limit, $since_id, $max_id, $since)
{
$qry =
'SELECT notice.id AS id ' .
'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' .
'WHERE notice_inbox.user_id = ' . $this->id . ' ' .
'AND notice.repeat_of IS NULL ';
if (!$own) {
// XXX: autoload notice inbox for constant
$inbox = new Notice_inbox();
$qry .= 'AND notice_inbox.source != ' . NOTICE_INBOX_SOURCE_GATEWAY . ' ';
}
if ($since_id != 0) {
$qry .= 'AND notice.id > ' . $since_id . ' ';
}
if ($max_id != 0) {
$qry .= 'AND notice.id <= ' . $max_id . ' ';
}
if (!is_null($since)) {
$qry .= 'AND notice.modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
}
// NOTE: we sort by fave time, not by notice time!
Fix for massively slow friends timeline query due to indexing bug introduced with repeats. Sorting on notice.id when our primary selector was notice_inbox.user_id caused a filesort and table scan of the notice table. Switchng to notice_inbox's notice_id means we can use our index, and everything comes right up. Before: mysql> explain SELECT notice.id AS id FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id WHERE notice_inbox.user_id = 18574 AND notice.repeat_of IS NULL ORDER BY notice.id DESC LIMIT 61 OFFSET 0; +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+----------------------------------------------+ | 1 | SIMPLE | notice_inbox | ref | PRIMARY,notice_inbox_notice_id_idx | PRIMARY | 4 | const | 102600 | Using index; Using temporary; Using filesort | | 1 | SIMPLE | notice | eq_ref | PRIMARY | PRIMARY | 4 | stoica.notice_inbox.notice_id | 1 | Using index | +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+----------------------------------------------+ After: mysql> explain SELECT notice.id AS id FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id WHERE notice_inbox.user_id = 18574 AND notice.repeat_of IS NULL ORDER BY notice_id DESC LIMIT 61 OFFSET 0; +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+--------------------------+ | 1 | SIMPLE | notice_inbox | ref | PRIMARY,notice_inbox_notice_id_idx | PRIMARY | 4 | const | 102816 | Using where; Using index | | 1 | SIMPLE | notice | eq_ref | PRIMARY,notice_repeatof_idx | PRIMARY | 4 | stoica.notice_inbox.notice_id | 1 | Using where | +----+-------------+--------------+--------+------------------------------------+---------+---------+-------------------------------+--------+--------------------------+
2009-12-23 13:18:27 +09:00
$qry .= 'ORDER BY notice_id DESC ';
if (!is_null($offset)) {
$qry .= "LIMIT $limit OFFSET $offset";
}
$ids = array();
$notice = new Notice();
$notice->query($qry);
while ($notice->fetch()) {
$ids[] = $notice->id;
}
$notice->free();
$notice = NULL;
return $ids;
}
2009-03-29 06:42:45 +09:00
function blowFavesCache()
{
$cache = common_memcache();
if ($cache) {
// Faves don't happen chronologically, so we need to blow
2009-03-29 06:42:45 +09:00
// ;last cache, too
2009-05-02 04:01:28 +09:00
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last'));
2009-07-06 00:32:57 +09:00
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id));
$cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id.';last'));
}
$profile = $this->getProfile();
$profile->blowFaveCount();
}
2009-03-29 06:42:45 +09:00
function getSelfTags()
{
return Profile_tag::getTags($this->id, $this->id);
}
2009-03-29 06:42:45 +09:00
function setSelfTags($newtags)
{
return Profile_tag::setTags($this->id, $this->id, $newtags);
}
function block($other)
{
2009-03-29 06:42:45 +09:00
// Add a new block record
// no blocking (and thus unsubbing from) yourself
if ($this->id == $other->id) {
common_log(LOG_WARNING,
sprintf(
"Profile ID %d (%s) tried to block his or herself.",
$profile->id,
$profile->nickname
)
);
return false;
}
$block = new Profile_block();
2009-03-29 06:42:45 +09:00
// Begin a transaction
$block->query('BEGIN');
$block->blocker = $this->id;
$block->blocked = $other->id;
$result = $block->insert();
if (!$result) {
common_log_db_error($block, 'INSERT', __FILE__);
return false;
}
2009-03-29 06:42:45 +09:00
// Cancel their subscription, if it exists
$otherUser = User::staticGet('id', $other->id);
if (!empty($otherUser)) {
subs_unsubscribe_to($otherUser, $this->getProfile());
}
$block->query('COMMIT');
return true;
}
function unblock($other)
{
2009-03-29 06:42:45 +09:00
// Get the block record
$block = Profile_block::get($this->id, $other->id);
if (!$block) {
return false;
}
$result = $block->delete();
if (!$result) {
common_log_db_error($block, 'DELETE', __FILE__);
return false;
}
return true;
}
function isMember($group)
{
$profile = $this->getProfile();
return $profile->isMember($group);
}
function isAdmin($group)
{
$profile = $this->getProfile();
return $profile->isAdmin($group);
}
2009-01-22 02:19:23 +09:00
2009-01-22 03:00:30 +09:00
function getGroups($offset=0, $limit=null)
2009-01-22 02:19:23 +09:00
{
$qry =
'SELECT user_group.* ' .
'FROM user_group JOIN group_member '.
'ON user_group.id = group_member.group_id ' .
'WHERE group_member.profile_id = %d ' .
'ORDER BY group_member.created DESC ';
if ($offset>0 && !is_null($limit)) {
if ($offset) {
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
2009-01-22 03:00:30 +09:00
}
}
$groups = new User_group();
$cnt = $groups->query(sprintf($qry, $this->id));
return $groups;
}
function getSubscriptions($offset=0, $limit=null)
{
$profile = $this->getProfile();
assert(!empty($profile));
return $profile->getSubscriptions($offset, $limit);
2009-01-22 03:00:30 +09:00
}
function getSubscribers($offset=0, $limit=null)
{
$profile = $this->getProfile();
assert(!empty($profile));
return $profile->getSubscribers($offset, $limit);
2009-01-22 02:19:23 +09:00
}
function getTaggedSubscribers($tag, $offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscriber ' .
'JOIN profile_tag ON (profile_tag.tagged = subscription.subscriber ' .
'AND profile_tag.tagger = subscription.subscribed) ' .
'WHERE subscription.subscribed = %d ' .
"AND profile_tag.tag = '%s' " .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if ($offset) {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
}
$profile = new Profile();
$cnt = $profile->query(sprintf($qry, $this->id, $tag));
return $profile;
}
function getTaggedSubscriptions($tag, $offset=0, $limit=null)
{
$qry =
'SELECT profile.* ' .
'FROM profile JOIN subscription ' .
'ON profile.id = subscription.subscribed ' .
'JOIN profile_tag on (profile_tag.tagged = subscription.subscribed ' .
'AND profile_tag.tagger = subscription.subscriber) ' .
'WHERE subscription.subscriber = %d ' .
"AND profile_tag.tag = '%s' " .
'AND subscription.subscribed != subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
$profile = new Profile();
$profile->query(sprintf($qry, $this->id, $tag));
return $profile;
}
2009-05-24 12:27:42 +09:00
function getDesign()
{
return Design::staticGet('id', $this->design_id);
}
2009-09-16 04:28:11 +09:00
function hasRight($right)
{
$profile = $this->getProfile();
return $profile->hasRight($right);
2009-09-16 04:28:11 +09:00
}
2009-07-27 04:06:38 +09:00
function delete()
{
$profile = $this->getProfile();
if ($profile) {
$profile->delete();
}
2009-07-27 04:06:38 +09:00
$related = array('Fave',
'Confirm_address',
'Remember_me',
'Foreign_link',
'Invitation',
2009-10-14 06:38:27 +09:00
'Notice_inbox',
2009-07-27 04:06:38 +09:00
);
Event::handle('UserDeleteRelated', array($this, &$related));
2009-07-27 04:06:38 +09:00
foreach ($related as $cls) {
$inst = new $cls();
$inst->user_id = $this->id;
$inst->delete();
}
$this->_deleteTags();
2009-10-03 04:29:57 +09:00
$this->_deleteBlocks();
2009-07-27 04:06:38 +09:00
parent::delete();
}
function _deleteTags()
{
$tag = new Profile_tag();
$tag->tagger = $this->id;
$tag->delete();
}
function _deleteBlocks()
{
$block = new Profile_block();
$block->blocker = $this->id;
$block->delete();
// XXX delete group block? Reset blocker?
}
2009-11-16 23:52:33 +09:00
function hasRole($name)
{
$profile = $this->getProfile();
return $profile->hasRole($name);
}
function grantRole($name)
{
$profile = $this->getProfile();
return $profile->grantRole($name);
}
function revokeRole($name)
{
$profile = $this->getProfile();
return $profile->revokeRole($name);
}
function isSandboxed()
{
2009-11-16 23:52:33 +09:00
$profile = $this->getProfile();
return $profile->isSandboxed();
}
function isSilenced()
{
2009-11-16 23:52:33 +09:00
$profile = $this->getProfile();
return $profile->isSilenced();
}
function repeatedByMe($offset=0, $limit=20, $since_id=null, $max_id=null)
{
$ids = Notice::stream(array($this, '_repeatedByMeDirect'),
array(),
'user:repeated_by_me:'.$this->id,
$offset, $limit, $since_id, $max_id, null);
return Notice::getStreamByIds($ids);
}
function _repeatedByMeDirect($offset, $limit, $since_id, $max_id, $since)
{
$notice = new Notice();
$notice->selectAdd(); // clears it
$notice->selectAdd('id');
$notice->profile_id = $this->id;
$notice->whereAdd('repeat_of IS NOT NULL');
$notice->orderBy('id DESC');
if (!is_null($offset)) {
$notice->limit($offset, $limit);
}
if ($since_id != 0) {
$notice->whereAdd('id > ' . $since_id);
}
if ($max_id != 0) {
$notice->whereAdd('id <= ' . $max_id);
}
if (!is_null($since)) {
$notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
}
$ids = array();
if ($notice->find()) {
while ($notice->fetch()) {
$ids[] = $notice->id;
}
}
$notice->free();
$notice = NULL;
return $ids;
}
2009-12-13 06:00:27 +09:00
function repeatsOfMe($offset=0, $limit=20, $since_id=null, $max_id=null)
{
$ids = Notice::stream(array($this, '_repeatsOfMeDirect'),
array(),
'user:repeats_of_me:'.$this->id,
$offset, $limit, $since_id, $max_id, null);
return Notice::getStreamByIds($ids);
}
function _repeatsOfMeDirect($offset, $limit, $since_id, $max_id, $since)
{
$qry =
'SELECT DISTINCT original.id AS id ' .
'FROM notice original JOIN notice rept ON original.id = rept.repeat_of ' .
'WHERE original.profile_id = ' . $this->id . ' ';
if ($since_id != 0) {
$qry .= 'AND original.id > ' . $since_id . ' ';
}
if ($max_id != 0) {
$qry .= 'AND original.id <= ' . $max_id . ' ';
}
if (!is_null($since)) {
$qry .= 'AND original.modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
}
// NOTE: we sort by fave time, not by notice time!
$qry .= 'ORDER BY original.id DESC ';
if (!is_null($offset)) {
$qry .= "LIMIT $limit OFFSET $offset";
}
$ids = array();
$notice = new Notice();
$notice->query($qry);
while ($notice->fetch()) {
$ids[] = $notice->id;
}
$notice->free();
$notice = NULL;
return $ids;
}
2009-12-13 06:15:23 +09:00
function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
{
$ids = Notice::stream(array($this, '_repeatedToMeDirect'),
array(),
'user:repeated_to_me:'.$this->id,
$offset, $limit, $since_id, $max_id, null);
return Notice::getStreamByIds($ids);
}
function _repeatedToMeDirect($offset, $limit, $since_id, $max_id, $since)
{
$qry =
'SELECT notice.id AS id ' .
'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' .
'WHERE notice_inbox.user_id = ' . $this->id . ' ' .
'AND notice.repeat_of IS NOT NULL ';
if ($since_id != 0) {
$qry .= 'AND notice.id > ' . $since_id . ' ';
}
if ($max_id != 0) {
$qry .= 'AND notice.id <= ' . $max_id . ' ';
}
if (!is_null($since)) {
$qry .= 'AND notice.modified > \'' . date('Y-m-d H:i:s', $since) . '\' ';
}
// NOTE: we sort by fave time, not by notice time!
$qry .= 'ORDER BY notice.id DESC ';
if (!is_null($offset)) {
$qry .= "LIMIT $limit OFFSET $offset";
}
$ids = array();
$notice = new Notice();
$notice->query($qry);
while ($notice->fetch()) {
$ids[] = $notice->id;
}
$notice->free();
$notice = NULL;
return $ids;
}
}