+
+ static function maxBio()
+ {
+ $biolimit = common_config('profile', 'biolimit');
+ // null => use global limit (distinct from 0!)
+ if (is_null($biolimit)) {
+ $biolimit = common_config('site', 'textlimit');
+ }
+ return $biolimit;
+ }
+
+ static function bioTooLong($bio)
+ {
+ $biolimit = self::maxBio();
+ return ($biolimit > 0 && !empty($bio) && (mb_strlen($bio) > $biolimit));
+ }
+
+ function delete()
+ {
+ $this->_deleteNotices();
+ $this->_deleteSubscriptions();
+ $this->_deleteMessages();
+ $this->_deleteTags();
+ $this->_deleteBlocks();
+
+ $related = array('Avatar',
+ 'Reply',
+ 'Group_member',
+ );
+
+ foreach ($related as $cls) {
+ $inst = new $cls();
+ $inst->profile_id = $this->id;
+ $inst->delete();
+ }
+
+ parent::delete();
+ }
+
+ function _deleteNotices()
+ {
+ $notice = new Notice();
+ $notice->profile_id = $this->id;
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ $other = clone($notice);
+ $other->delete();
+ }
+ }
+ }
+
+ function _deleteSubscriptions()
+ {
+ $sub = new Subscription();
+ $sub->subscriber = $this->id;
+ $sub->delete();
+
+ $subd = new Subscription();
+ $subd->subscribed = $this->id;
+ $subd->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();
+ $tag->tagged = $this->id;
+ $tag->delete();
+ }
+
+ function _deleteBlocks()
+ {
+ $block = new Profile_block();
+ $block->blocked = $this->id;
+ $block->delete();
+
+ $block = new Group_block();
+ $block->blocked = $this->id;
+ $block->delete();
+ }
+
+ // XXX: identical to Notice::getLocation.
+
+ function getLocation()
+ {
+ $location = null;
+
+ if (!empty($this->location_id) && !empty($this->location_ns)) {
+ $location = Location::fromId($this->location_id, $this->location_ns);
+ }
+
+ if (is_null($location)) { // no ID, or Location::fromId() failed
+ if (!empty($this->lat) && !empty($this->lon)) {
+ $location = Location::fromLatLon($this->lat, $this->lon);
+ }
+ }
+
+ if (is_null($location)) { // still haven't found it!
+ if (!empty($this->location)) {
+ $location = Location::fromName($this->location);
+ }
+ }
+
+ return $location;
+ }
+
+ function hasRole($name)
+ {
+ $has_role = false;
+ if (Event::handle('StartHasRole', array($this, $name, &$has_role))) {
+ $role = Profile_role::pkeyGet(array('profile_id' => $this->id,
+ 'role' => $name));
+ $has_role = !empty($role);
+ Event::handle('EndHasRole', array($this, $name, $has_role));
+ }
+ return $has_role;
+ }
+
+ function grantRole($name)
+ {
+ $role = new Profile_role();
+
+ $role->profile_id = $this->id;
+ $role->role = $name;
+ $role->created = common_sql_now();
+
+ $result = $role->insert();
+
+ if (!$result) {
+ common_log_db_error($role, 'INSERT', __FILE__);
+ return false;
+ }
+
+ return true;
+ }
+
+ function revokeRole($name)
+ {
+ $role = Profile_role::pkeyGet(array('profile_id' => $this->id,
+ 'role' => $name));
+
+ if (empty($role)) {
+ throw new Exception('Cannot revoke role "'.$name.'" for user #'.$this->id.'; does not exist.');
+ }
+
+ $result = $role->delete();
+
+ if (!$result) {
+ common_log_db_error($role, 'DELETE', __FILE__);
+ throw new Exception('Cannot revoke role "'.$name.'" for user #'.$this->id.'; database error.');
+ }
+
+ return true;
+ }
+
+ function isSandboxed()
+ {
+ return $this->hasRole(Profile_role::SANDBOXED);
+ }
+
+ function isSilenced()
+ {
+ return $this->hasRole(Profile_role::SILENCED);
+ }
+
+ function sandbox()
+ {
+ $this->grantRole(Profile_role::SANDBOXED);
+ }
+
+ function unsandbox()
+ {
+ $this->revokeRole(Profile_role::SANDBOXED);
+ }
+
+ function silence()
+ {
+ $this->grantRole(Profile_role::SILENCED);
+ }
+
+ function unsilence()
+ {
+ $this->revokeRole(Profile_role::SILENCED);
+ }
+
+ /**
+ * Does this user have the right to do X?
+ *
+ * With our role-based authorization, this is merely a lookup for whether the user
+ * has a particular role. The implementation currently uses a switch statement
+ * to determine if the user has the pre-defined role to exercise the right. Future
+ * implementations may allow per-site roles, and different mappings of roles to rights.
+ *
+ * @param $right string Name of the right, usually a constant in class Right
+ * @return boolean whether the user has the right in question
+ */
+
+ function hasRight($right)
+ {
+ $result = false;
+ if (Event::handle('UserRightsCheck', array($this, $right, &$result))) {
+ switch ($right)
+ {
+ case Right::DELETEOTHERSNOTICE:
+ case Right::SANDBOXUSER:
+ case Right::SILENCEUSER:
+ case Right::DELETEUSER:
+ $result = $this->hasRole(Profile_role::MODERATOR);
+ break;
+ case Right::CONFIGURESITE:
+ $result = $this->hasRole(Profile_role::ADMINISTRATOR);
+ break;
+ case Right::NEWNOTICE:
+ case Right::NEWMESSAGE:
+ case Right::SUBSCRIBE:
+ $result = !$this->isSilenced();
+ break;
+ case Right::PUBLICNOTICE:
+ case Right::EMAILONREPLY:
+ case Right::EMAILONSUBSCRIBE:
+ case Right::EMAILONFAVE:
+ $result = !$this->isSandboxed();
+ break;
+ default:
+ $result = false;
+ break;
+ }
+ }
+ return $result;
+ }