X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FProfile.php;h=db8326f0f6959dbd090e39dda6ef7bfe1f77e60e;hb=b53e1439969bfa2c0b551d8cc2fc8fe15652c62a;hp=fe2ce343d7bf92f6eec42e1ece2a2c6aafaf7e41;hpb=1056348029f18507581921e0bfa9b4473964d97c;p=quix0rs-gnu-social.git diff --git a/classes/Profile.php b/classes/Profile.php index fe2ce343d7..db8326f0f6 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -22,8 +22,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } /** * Table Definition for profile */ -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; - class Profile extends Managed_DataObject { ###START_AUTOCODE @@ -32,11 +30,11 @@ class Profile extends Managed_DataObject public $__table = 'profile'; // table name public $id; // int(4) primary_key not_null public $nickname; // varchar(64) multiple_key not_null - public $fullname; // varchar(255) multiple_key - public $profileurl; // varchar(255) - public $homepage; // varchar(255) multiple_key + public $fullname; // varchar(191) multiple_key not 255 because utf8mb4 takes more space + public $profileurl; // varchar(191) not 255 because utf8mb4 takes more space + public $homepage; // varchar(191) multiple_key not 255 because utf8mb4 takes more space public $bio; // text() multiple_key - public $location; // varchar(255) multiple_key + public $location; // varchar(191) multiple_key not 255 because utf8mb4 takes more space public $lat; // decimal(10,7) public $lon; // decimal(10,7) public $location_id; // int(4) @@ -51,11 +49,11 @@ class Profile extends Managed_DataObject 'fields' => array( 'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'), 'nickname' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'nickname or username', 'collate' => 'utf8_general_ci'), - 'fullname' => array('type' => 'varchar', 'length' => 255, 'description' => 'display name', 'collate' => 'utf8_general_ci'), - 'profileurl' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL, cached so we dont regenerate'), - 'homepage' => array('type' => 'varchar', 'length' => 255, 'description' => 'identifying URL', 'collate' => 'utf8_general_ci'), + 'fullname' => array('type' => 'varchar', 'length' => 191, 'description' => 'display name', 'collate' => 'utf8_general_ci'), + 'profileurl' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL, cached so we dont regenerate'), + 'homepage' => array('type' => 'varchar', 'length' => 191, 'description' => 'identifying URL', 'collate' => 'utf8_general_ci'), 'bio' => array('type' => 'text', 'description' => 'descriptive biography', 'collate' => 'utf8_general_ci'), - 'location' => array('type' => 'varchar', 'length' => 255, 'description' => 'physical location', 'collate' => 'utf8_general_ci'), + 'location' => array('type' => 'varchar', 'length' => 191, 'description' => 'physical location', 'collate' => 'utf8_general_ci'), 'lat' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'latitude'), 'lon' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'longitude'), 'location_id' => array('type' => 'int', 'description' => 'location id if possible'), @@ -92,32 +90,32 @@ class Profile extends Managed_DataObject return $user->getProfile(); } - protected $_user = -1; // Uninitialized value distinct from null + protected $_user = array(); public function getUser() { - if ($this->_user === -1) { - $this->_user = User::getKV('id', $this->id); - } - if (!$this->_user instanceof User) { - throw new NoSuchUserException(array('id'=>$this->id)); + if (!isset($this->_user[$this->id])) { + $user = User::getKV('id', $this->id); + if (!$user instanceof User) { + throw new NoSuchUserException(array('id'=>$this->id)); + } + $this->_user[$this->id] = $user; } - - return $this->_user; + return $this->_user[$this->id]; } - protected $_group = -1; + protected $_group = array(); public function getGroup() { - if ($this->_group === -1) { - $this->_group = User_group::getKV('profile_id', $this->id); - } - if (!$this->_group instanceof User_group) { - throw new NoSuchGroupException(array('profile_id'=>$this->id)); + if (!isset($this->_group[$this->id])) { + $group = User_group::getKV('profile_id', $this->id); + if (!$group instanceof User_group) { + throw new NoSuchGroupException(array('profile_id'=>$this->id)); + } + $this->_group[$this->id] = $group; } - - return $this->_group; + return $this->_group[$this->id]; } public function isGroup() @@ -140,7 +138,15 @@ class Profile extends Managed_DataObject return true; } - protected $_avatars = array(); + public function getObjectType() + { + // FIXME: More types... like peopletags and whatever + if ($this->isGroup()) { + return ActivityObject::GROUP; + } else { + return ActivityObject::PERSON; + } + } public function getAvatar($width, $height=null) { @@ -149,7 +155,12 @@ class Profile extends Managed_DataObject public function setOriginal($filename) { - $imagefile = new ImageFile($this->id, Avatar::path($filename)); + if ($this->isGroup()) { + // Until Group avatars are handled just like profile avatars. + return $this->getGroup()->setOriginal($filename); + } + + $imagefile = new ImageFile(null, Avatar::path($filename)); $avatar = new Avatar(); $avatar->profile_id = $this->id; @@ -168,17 +179,6 @@ class Profile extends Managed_DataObject return null; } - foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) { - // We don't do a scaled one if original is our scaled size - if (!($avatar->width == $size && $avatar->height == $size)) { - try { - Avatar::newSize($this, $size); - } catch (Exception $e) { - // should we abort the generation and live without smaller avatars? - } - } - } - return $avatar; } @@ -237,9 +237,9 @@ class Profile extends Managed_DataObject return $notice->_items[0]; } return $notice; - } else { - return null; } + + return null; } function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0) @@ -310,7 +310,7 @@ class Profile extends Managed_DataObject } try { - return User_group::listFind('id', $ids); + return User_group::multiGet('id', $ids); } catch (NoResultException $e) { return null; // throw exception when we handle it everywhere } @@ -598,7 +598,7 @@ class Profile extends Managed_DataObject { $subs = Subscription::getSubscribedIDs($this->id, $offset, $limit); try { - $profiles = Profile::listFind('id', $subs); + $profiles = Profile::multiGet('id', $subs); } catch (NoResultException $e) { return $e->obj; } @@ -609,7 +609,7 @@ class Profile extends Managed_DataObject { $subs = Subscription::getSubscriberIDs($this->id, $offset, $limit); try { - $profiles = Profile::listFind('id', $subs); + $profiles = Profile::multiGet('id', $subs); } catch (NoResultException $e) { return $e->obj; } @@ -756,7 +756,7 @@ class Profile extends Managed_DataObject * @param Profile $other * @return boolean */ - function hasPendingSubscription($other) + function hasPendingSubscription(Profile $other) { return Subscription_queue::exists($this, $other); } @@ -767,45 +767,12 @@ class Profile extends Managed_DataObject * @param Profile $other * @return boolean */ - function mutuallySubscribed($other) + function mutuallySubscribed(Profile $other) { return $this->isSubscribed($other) && $other->isSubscribed($this); } - function hasFave($notice) - { - $fave = Fave::pkeyGet(array('user_id' => $this->id, - 'notice_id' => $notice->id)); - return ((is_null($fave)) ? false : true); - } - - function faveCount() - { - $c = Cache::instance(); - if (!empty($c)) { - $cnt = $c->get(Cache::key('profile:fave_count:'.$this->id)); - if (is_integer($cnt)) { - return (int) $cnt; - } - } - - $faves = new Fave(); - $faves->user_id = $this->id; - $cnt = (int) $faves->count('notice_id'); - - if (!empty($c)) { - $c->set(Cache::key('profile:fave_count:'.$this->id), $cnt); - } - - return $cnt; - } - - function favoriteNotices($own=false, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0) - { - return Fave::stream($this->id, $offset, $limit, $own, $since_id, $max_id); - } - function noticeCount() { $c = Cache::instance(); @@ -828,20 +795,6 @@ class Profile extends Managed_DataObject return $cnt; } - function blowFavesCache() - { - $cache = Cache::instance(); - if ($cache) { - // Faves don't happen chronologically, so we need to blow - // ;last cache, too - $cache->delete(Cache::key('fave:ids_by_user:'.$this->id)); - $cache->delete(Cache::key('fave:ids_by_user:'.$this->id.';last')); - $cache->delete(Cache::key('fave:ids_by_user_own:'.$this->id)); - $cache->delete(Cache::key('fave:ids_by_user_own:'.$this->id.';last')); - } - $this->blowFaveCount(); - } - function blowSubscriberCount() { $c = Cache::instance(); @@ -858,14 +811,6 @@ class Profile extends Managed_DataObject } } - function blowFaveCount() - { - $c = Cache::instance(); - if (!empty($c)) { - $c->delete(Cache::key('profile:fave_count:'.$this->id)); - } - } - function blowNoticeCount() { $c = Cache::instance(); @@ -898,12 +843,8 @@ class Profile extends Managed_DataObject common_debug("Updating User ({$this->id}) nickname from {$dataObject->nickname} to {$this->nickname}"); $origuser = clone($local); $local->nickname = $this->nickname; - $result = $local->updateKeys($origuser); - if ($result === false) { - common_log_db_error($local, 'UPDATE', __FILE__); - // TRANS: Server error thrown when user profile settings could not be updated. - throw new ServerException(_('Could not update user nickname.')); - } + // updateWithKeys throws exception on failure. + $local->updateWithKeys($origuser); // Clear the site owner, in case nickname changed if ($local->hasRole(Profile_role::OWNER)) { @@ -921,9 +862,9 @@ class Profile extends Managed_DataObject { $this->_deleteNotices(); $this->_deleteSubscriptions(); - $this->_deleteMessages(); $this->_deleteTags(); $this->_deleteBlocks(); + $this->_deleteAttentions(); Avatar::deleteFromProfile($this, true); // Warning: delete() will run on the batch objects, @@ -996,17 +937,6 @@ class Profile extends Managed_DataObject $self->delete(); } - function _deleteMessages() - { - $msg = new Message(); - $msg->from_profile = $this->id; - $msg->delete(); - - $msg = new Message(); - $msg->to_profile = $this->id; - $msg->delete(); - } - function _deleteTags() { $tag = new Profile_tag(); @@ -1025,6 +955,20 @@ class Profile extends Managed_DataObject $block->delete(); } + function _deleteAttentions() + { + $att = new Attention(); + $att->profile_id = $this->getID(); + + if ($att->find()) { + while ($att->fetch()) { + // Can't do delete() on the object directly since it won't remove all of it + $other = clone($att); + $other->delete(); + } + } + } + // XXX: identical to Notice::getLocation. public function getLocation() @@ -1311,20 +1255,20 @@ class Profile extends Managed_DataObject * Clients use some extra profile info in the atom stream. * This gives it to them. * - * @param User $cur Current user + * @param Profile $scoped The currently logged in/scoped profile * * @return array representation of element or null */ - function profileInfo($cur) + function profileInfo(Profile $scoped=null) { $profileInfoAttr = array('local_id' => $this->id); - if ($cur != null) { + if ($scoped instanceof Profile) { // Whether the current user is a subscribed to this profile - $profileInfoAttr['following'] = $cur->isSubscribed($this) ? 'true' : 'false'; + $profileInfoAttr['following'] = $scoped->isSubscribed($this) ? 'true' : 'false'; // Whether the current user is has blocked this profile - $profileInfoAttr['blocking'] = $cur->hasBlocked($this) ? 'true' : 'false'; + $profileInfoAttr['blocking'] = $scoped->hasBlocked($this) ? 'true' : 'false'; } return array('statusnet:profile_info', $profileInfoAttr, null); @@ -1356,10 +1300,67 @@ class Profile extends Managed_DataObject */ function asActivityNoun($element) { - $noun = ActivityObject::fromProfile($this); + $noun = $this->asActivityObject(); return $noun->asString('activity:' . $element); } + public function asActivityObject() + { + $object = new ActivityObject(); + + if (Event::handle('StartActivityObjectFromProfile', array($this, &$object))) { + $object->type = $this->getObjectType(); + $object->id = $this->getUri(); + $object->title = $this->getBestName(); + $object->link = $this->getUrl(); + $object->summary = $this->getDescription(); + + try { + $avatar = Avatar::getUploaded($this); + $object->avatarLinks[] = AvatarLink::fromAvatar($avatar); + } catch (NoAvatarException $e) { + // Could not find an original avatar to link + } + + $sizes = array( + AVATAR_PROFILE_SIZE, + AVATAR_STREAM_SIZE, + AVATAR_MINI_SIZE + ); + + foreach ($sizes as $size) { + $alink = null; + try { + $avatar = Avatar::byProfile($this, $size); + $alink = AvatarLink::fromAvatar($avatar); + } catch (NoAvatarException $e) { + $alink = new AvatarLink(); + $alink->type = 'image/png'; + $alink->height = $size; + $alink->width = $size; + $alink->url = Avatar::defaultImage($size); + } + + $object->avatarLinks[] = $alink; + } + + if (isset($this->lat) && isset($this->lon)) { + $object->geopoint = (float)$this->lat + . ' ' . (float)$this->lon; + } + + $object->poco = PoCo::fromProfile($this); + + if ($this->isLocal()) { + $object->extra[] = array('followers', array('url' => common_local_url('subscribers', array('nickname' => $this->getNickname())))); + } + + Event::handle('EndActivityObjectFromProfile', array($this, &$object)); + } + + return $object; + } + /** * Returns the profile's canonical url, not necessarily a uri/unique id * @@ -1374,6 +1375,16 @@ class Profile extends Managed_DataObject return $this->profileurl; } + public function getNickname() + { + return $this->nickname; + } + + public function getDescription() + { + return $this->bio; + } + /** * Returns the best URI for a profile. Plugins may override. * @@ -1388,9 +1399,8 @@ class Profile extends Managed_DataObject // check for a local user first $user = User::getKV('id', $this->id); - - if (!empty($user)) { - $uri = $user->uri; + if ($user instanceof User) { + $uri = $user->getUri(); } Event::handle('EndGetProfileUri', array($this, &$uri)); @@ -1441,19 +1451,35 @@ class Profile extends Managed_DataObject return $feed; } - static function fromURI($uri) + public function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null) + { + // TRANS: Exception thrown when trying view "repeated to me". + throw new Exception(_('Not implemented since inbox change.')); + } + + /* + * Get a Profile object by URI. Will call external plugins for help + * using the event StartGetProfileFromURI. + * + * @param string $uri A unique identifier for a resource (profile/group/whatever) + */ + static function fromUri($uri) { $profile = null; if (Event::handle('StartGetProfileFromURI', array($uri, &$profile))) { - // Get a local user + // Get a local user when plugin lookup (like OStatus) fails $user = User::getKV('uri', $uri); - if (!empty($user)) { + if ($user instanceof User) { $profile = $user->getProfile(); } Event::handle('EndGetProfileFromURI', array($uri, $profile)); } + if (!$profile instanceof Profile) { + throw new UnknownUriException($uri); + } + return $profile; } @@ -1521,7 +1547,7 @@ class Profile extends Managed_DataObject function __sleep() { $vars = parent::__sleep(); - $skip = array('_user', '_avatars'); + $skip = array('_user', '_group'); return array_diff($vars, $skip); } @@ -1529,4 +1555,52 @@ class Profile extends Managed_DataObject { return $this; } + + /** + * This will perform shortenLinks with the connected User object. + * + * Won't work on remote profiles or groups, so expect a + * NoSuchUserException if you don't know it's a local User. + * + * @param string $text String to shorten + * @param boolean $always Disrespect minimum length etc. + * + * @return string link-shortened $text + */ + public function shortenLinks($text, $always=false) + { + return $this->getUser()->shortenLinks($text, $always); + } + + public function isPrivateStream() + { + // We only know of public remote users as of yet... + if (!$this->isLocal()) { + return false; + } + return $this->getUser()->private_stream ? true : false; + } + + public function delPref($namespace, $topic) { + return Profile_prefs::setData($this, $namespace, $topic, null); + } + + public function getPref($namespace, $topic, $default=null) { + // If you want an exception to be thrown, call Profile_prefs::getData directly + try { + return Profile_prefs::getData($this, $namespace, $topic, $default); + } catch (NoResultException $e) { + return null; + } + } + + // The same as getPref but will fall back to common_config value for the same namespace/topic + public function getConfigPref($namespace, $topic) + { + return Profile_prefs::getConfigData($this, $namespace, $topic); + } + + public function setPref($namespace, $topic, $data) { + return Profile_prefs::setData($this, $namespace, $topic, $data); + } }