X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=classes%2FUser.php;h=3efaa5e72131b5ba7cda2262ba4e4879d0277b1d;hb=a39f51c0441b22951412b2c00d88c34f39cb39c9;hp=1ccbdbc2174c20128845b19247040ff9d9030ab6;hpb=0a20abf1d8a9a068df9310d6903cc303f39b25ed;p=quix0rs-gnu-social.git diff --git a/classes/User.php b/classes/User.php index 1ccbdbc217..3efaa5e721 100644 --- a/classes/User.php +++ b/classes/User.php @@ -34,9 +34,9 @@ class User extends Managed_DataObject 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 $password; // varchar(191) not 255 because utf8mb4 takes more space + public $email; // varchar(191) unique_key not 255 because utf8mb4 takes more space + public $incomingemail; // varchar(191) unique_key not 255 because utf8mb4 takes more space public $emailnotifysub; // tinyint(1) default_1 public $emailnotifyfav; // tinyint(1) default_1 public $emailnotifynudge; // tinyint(1) default_1 @@ -50,8 +50,8 @@ class User extends Managed_DataObject public $carrier; // int(4) public $smsnotify; // tinyint(1) public $smsreplies; // tinyint(1) - public $smsemail; // varchar(255) - public $uri; // varchar(255) unique_key + public $smsemail; // varchar(191) not 255 because utf8mb4 takes more space + public $uri; // varchar(191) unique_key not 255 because utf8mb4 takes more space public $autosubscribe; // tinyint(1) public $subscribe_policy; // tinyint(1) public $urlshorteningservice; // varchar(50) default_ur1.ca @@ -69,9 +69,9 @@ class User extends Managed_DataObject 'fields' => array( 'id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'), 'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname or username, duped in profile'), - 'password' => array('type' => 'varchar', 'length' => 255, 'description' => 'salted password, can be null for OpenID users'), - 'email' => array('type' => 'varchar', 'length' => 255, 'description' => 'email address for password recovery etc.'), - 'incomingemail' => array('type' => 'varchar', 'length' => 255, 'description' => 'email address for post-by-email'), + 'password' => array('type' => 'varchar', 'length' => 191, 'description' => 'salted password, can be null for OpenID users'), + 'email' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for password recovery etc.'), + 'incomingemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for post-by-email'), 'emailnotifysub' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of subscriptions'), 'emailnotifyfav' => array('type' => 'int', 'size' => 'tiny', 'default' => null, 'description' => 'Notify by email of favorites'), 'emailnotifynudge' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of nudges'), @@ -85,8 +85,8 @@ class User extends Managed_DataObject 'carrier' => array('type' => 'int', 'description' => 'foreign key to sms_carrier'), 'smsnotify' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS'), 'smsreplies' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS on replies'), - 'smsemail' => array('type' => 'varchar', 'length' => 255, 'description' => 'built from sms and carrier'), - 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'), + 'smsemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'built from sms and carrier'), + 'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'), 'autosubscribe' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'automatically subscribe to users who subscribe to us'), 'subscribe_policy' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => '0 = anybody can subscribe; 1 = require approval'), 'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'), @@ -152,34 +152,6 @@ class User extends Managed_DataObject return $this->getProfile()->hasPendingSubscription($other); } - // 'update' won't write key columns, so we have to do it ourselves. - - function updateKeys(&$orig) - { - $this->_connect(); - $parts = array(); - foreach (array('nickname', 'email', 'incomingemail', 'sms', 'carrier', 'smsemail') as $k) { - if (strcmp($this->$k, $orig->$k) != 0) { - $parts[] = $k . ' = ' . $this->_quote($this->$k); - } - } - if (count($parts) == 0) { - // 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; - } - /** * Get the most recent notice posted by this user, if any. * @@ -219,7 +191,8 @@ class User extends Managed_DataObject * 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 + * @return User object + * @throws Exception on failure */ static function register(array $fields) { @@ -233,12 +206,8 @@ class User extends Managed_DataObject $email = common_canonical_email($email); } - try { - $profile->nickname = Nickname::normalize($nickname, true); - } catch (NicknameException $e) { - common_log(LOG_WARNING, sprintf('Bad nickname during User registration for %s: %s', $nickname, $e->getMessage()), __FILE__); - return false; - } + // Normalize _and_ check whether it is in use. Throw NicknameException on failure. + $profile->nickname = Nickname::normalize($nickname, true); $profile->profileurl = common_profile_url($profile->nickname); @@ -276,7 +245,7 @@ class User extends Managed_DataObject if (!empty($code)) { $invite = Invitation::getKV($code); - if ($invite && $invite->address && $invite->address_type == 'email' && $invite->address == $email) { + if ($invite instanceof Invitation && $invite->address && $invite->address_type == 'email' && $invite->address == $email) { $user->email = $invite->address; } } @@ -305,7 +274,9 @@ class User extends Managed_DataObject $id = $profile->insert(); if ($id === false) { common_log_db_error($profile, 'INSERT', __FILE__); - return false; + $profile->query('ROLLBACK'); + // TRANS: Profile data could not be inserted for some reason. + throw new ServerException(_m('Could not insert profile data for new user.')); } $user->id = $id; @@ -325,7 +296,8 @@ class User extends Managed_DataObject if ($result === false) { common_log_db_error($user, 'INSERT', __FILE__); $profile->query('ROLLBACK'); - return false; + // TRANS: User data could not be inserted for some reason. + throw new ServerException(_m('Could not insert user data for new user.')); } // Everyone is subscribed to themself @@ -340,7 +312,8 @@ class User extends Managed_DataObject if (!$result) { common_log_db_error($subscription, 'INSERT', __FILE__); $profile->query('ROLLBACK'); - return false; + // TRANS: Subscription data could not be inserted for some reason. + throw new ServerException(_m('Could not insert subscription data for new user.')); } // Mark that this invite was converted @@ -362,7 +335,8 @@ class User extends Managed_DataObject if (!$result) { common_log_db_error($confirm, 'INSERT', __FILE__); $profile->query('ROLLBACK'); - return false; + // TRANS: Email confirmation data could not be inserted for some reason. + throw new ServerException(_m('Could not insert email confirmation data for new user.')); } } @@ -380,7 +354,7 @@ class User extends Managed_DataObject common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), __FILE__); } else { - Subscription::start($profile, $defuser->getProfile()); + Subscription::ensureStart($profile, $defuser->getProfile()); } } @@ -413,6 +387,10 @@ class User extends Managed_DataObject Event::handle('EndUserRegister', array($profile)); } + if (!$user instanceof User) { + throw new ServerException('User could not be registered. Probably an event hook that failed.'); + } + return $user; } @@ -686,6 +664,21 @@ class User extends Managed_DataObject return $this->getProfile()->isSilenced(); } + function receivesEmailNotifications() + { + // We could do this in one large if statement, but that's not as easy to read + // Don't send notifications if we don't know the user's email address or it is + // explicitly undesired by the user's own settings. + if (empty($this->email) || !$this->emailnotifyattn) { + return false; + } + // Don't send notifications to a user who is sandboxed or silenced + if ($this->isSandboxed() || $this->isSilenced()) { + return false; + } + return true; + } + function repeatedByMe($offset=0, $limit=20, $since_id=null, $max_id=null) { $stream = new RepeatedByMeNoticeStream($this); @@ -700,11 +693,9 @@ class User extends Managed_DataObject return $stream->getNotices($offset, $limit, $since_id, $max_id); } - - function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null) + 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.')); + return $this->getProfile()->repeatedToMe($offset, $limit, $since_id, $max_id); } public static function siteOwner() @@ -862,57 +853,59 @@ class User extends Managed_DataObject static function recoverPassword($nore) { - $user = User::getKV('email', common_canonical_email($nore)); - - if (!$user) { - try { - $user = User::getKV('nickname', common_canonical_nickname($nore)); - } catch (NicknameException $e) { - // invalid + // $confirm_email will be used as a fallback if our user doesn't have a confirmed email + $confirm_email = null; + + if (common_is_email($nore)) { + $user = User::getKV('email', common_canonical_email($nore)); + + // See if it's an unconfirmed email address + if (!$user instanceof User) { + // Warning: it may actually be legit to have multiple folks + // who have claimed, but not yet confirmed, the same address. + // We'll only send to the first one that comes up. + $confirm_email = new Confirm_address(); + $confirm_email->address = common_canonical_email($nore); + $confirm_email->address_type = 'email'; + if ($confirm_email->find(true)) { + $user = User::getKV('id', $confirm_email->user_id); + } } - } - // See if it's an unconfirmed email address - - if (!$user) { - // Warning: it may actually be legit to have multiple folks - // who have claimed, but not yet confirmed, the same address. - // We'll only send to the first one that comes up. - $confirm_email = new Confirm_address(); - $confirm_email->address = common_canonical_email($nore); - $confirm_email->address_type = 'email'; - $confirm_email->find(); - if ($confirm_email->fetch()) { - $user = User::getKV($confirm_email->user_id); - } else { - $confirm_email = null; + // No luck finding anyone by that email address. + if (!$user instanceof User) { + if (common_config('site', 'fakeaddressrecovery')) { + // Return without actually doing anything! We fake address recovery + // to avoid revealing which email addresses are registered with the site. + return; + } + // TRANS: Information on password recovery form if no known e-mail address was specified. + throw new ClientException(_('No user with that email address exists here.')); } } else { - $confirm_email = null; - } - - if (!$user) { - // TRANS: Information on password recovery form if no known username or e-mail address was specified. - throw new ClientException(_('No user with that email address or username.')); - return; + // This might throw a NicknameException on bad nicknames + $user = User::getKV('nickname', common_canonical_nickname($nore)); + if (!$user instanceof User) { + // TRANS: Information on password recovery form if no known username was specified. + throw new ClientException(_('No user with that nickname exists here.')); + } } // Try to get an unconfirmed email address if they used a user name - - if (!$user->email && !$confirm_email) { + if (empty($user->email) && $confirm_email === null) { $confirm_email = new Confirm_address(); $confirm_email->user_id = $user->id; $confirm_email->address_type = 'email'; $confirm_email->find(); if (!$confirm_email->fetch()) { + // Nothing found, so let's reset it to null $confirm_email = null; } } - if (!$user->email && !$confirm_email) { + if (empty($user->email) && !$confirm_email instanceof Confirm_address) { // TRANS: Client error displayed on password recovery form if a user does not have a registered e-mail address. throw new ClientException(_('No registered email address for that user.')); - return; } // Success! We have a valid user and a confirmed or unconfirmed email address @@ -921,13 +914,12 @@ class User extends Managed_DataObject $confirm->code = common_confirmation_code(128); $confirm->address_type = 'recover'; $confirm->user_id = $user->id; - $confirm->address = (!empty($user->email)) ? $user->email : $confirm_email->address; + $confirm->address = $user->email ?: $confirm_email->address; if (!$confirm->insert()) { common_log_db_error($confirm, 'INSERT', __FILE__); // TRANS: Server error displayed if e-mail address confirmation fails in the database on the password recovery form. throw new ServerException(_('Error saving address confirmation.')); - return; } // @todo FIXME: needs i18n. @@ -1007,11 +999,26 @@ class User extends Managed_DataObject return $act; } + public function isPrivateStream() + { + return $this->getProfile()->isPrivateStream(); + } + + public function delPref($namespace, $topic) + { + return $this->getProfile()->delPref($namespace, $topic); + } + public function getPref($namespace, $topic, $default=null) { return $this->getProfile()->getPref($namespace, $topic, $default); } + public function getConfigPref($namespace, $topic) + { + return $this->getProfile()->getConfigPref($namespace, $topic); + } + public function setPref($namespace, $topic, $data) { return $this->getProfile()->setPref($namespace, $topic, $data);