execute(array($user_id))->fetchOneRow(); if ($row) { self::$cache[$user_id] = new User($row); } else { self::$cache[$user_id] = null; } } return self::$cache[$user_id]; } /** * Find the user with a specified user_id. * * @param string $identifier * * @return User|null */ public static function findByIdentifier($identifier) { $user_id = WT_DB::prepare( "SELECT SQL_CACHE user_id FROM `##user` WHERE ? IN (user_name, email)" )->execute(array($identifier))->fetchOne(); return self::find($user_id); } /** * Find the user with a specified genealogy record. * * @param WT_Tree $tree * @param WT_Individual $individual * * @return User|null */ public static function findByGenealogyRecord(WT_Tree $tree, $individual) { $user_id = WT_DB::prepare( "SELECT SQL_CACHE user_id" . " FROM `##user_gedcom_setting`" . " WHERE gedcom_id = ? AND setting_name = 'gedcomid' AND setting_value = ?" )->execute(array($tree->tree_id, $individual->getXref()))->fetchOne(); return self::find($user_id); } /** * Find the latest user to register. * * @return User|null */ public static function findLatestToRegister() { $user_id = WT_DB::prepare( "SELECT SQL_CACHE u.user_id" . " FROM `##user` u" . " LEFT JOIN `##user_setting` us ON (u.user_id=us.user_id AND us.setting_name='reg_timestamp') " . " ORDER BY us.setting_value DESC LIMIT 1" )->execute()->fetchOne(); return self::find($user_id); } /** * Create a new user. * * The calling code needs to check for duplicates identifiers before calling * this function. * * @param string $user_name * @param string $real_name * @param string $email * @param string $password * * @return User */ public static function create($user_name, $real_name, $email, $password) { WT_DB::prepare( "INSERT INTO `##user` (user_name, real_name, email, password) VALUES (?, ?, ?, ?)" )->execute(array($user_name, $real_name, $email, password_hash($password, PASSWORD_DEFAULT))); return User::findByIdentifier($user_name); } /** * Get a count of all users. * * @return int */ public static function count() { return (int)WT_DB::prepare( "SELECT SQL_CACHE COUNT(*)" . " FROM `##user`" . " WHERE user_id > 0" )->fetchOne(); } /** * Get a list of all users. * * @return User[] */ public static function all() { $users = array(); $rows = WT_DB::prepare( "SELECT SQL_CACHE user_id, user_name, real_name, email" . " FROM `##user`" . " WHERE user_id > 0" . " ORDER BY user_name" )->fetchAll(); foreach ($rows as $row) { $users[] = new User($row); } return $users; } /** * Get a list of all administrators. * * @return User[] */ public static function allAdmins() { $rows = WT_DB::prepare( "SELECT SQL_CACHE user_id, user_name, real_name, email" . " FROM `##user`" . " JOIN `##user_setting` USING (user_id)" . " WHERE user_id > 0" . " AND setting_name = 'canadmin'" . " AND setting_value = '1'" )->fetchAll(); $users = array(); foreach ($rows as $row) { $users[] = new User($row); } return $users; } /** * Get a list of all users who are currently logged in. * * @return User[] */ public static function allLoggedIn() { $rows = WT_DB::prepare( "SELECT SQL_NO_CACHE DISTINCT user_id, user_name, real_name, email". " FROM `##user`". " JOIN `##session` USING (user_id)" )->fetchAll(); $users = array(); foreach ($rows as $row) { $users[] = new User($row); } return $users; } /** * Create a new user object from a row in the database. * * @param \stdclass $user A row from the wt_user table */ private function __construct(\stdClass $user) { $this->user_id = $user->user_id; $this->user_name = $user->user_name; $this->real_name = $user->real_name; $this->email = $user->email; } /** * Delete a user */ function delete() { // Don't delete the logs. WT_DB::prepare("UPDATE `##log` SET user_id=NULL WHERE user_id =?")->execute(array($this->user_id)); // Take over the user’s pending changes. (What else could we do with them?) WT_DB::prepare("DELETE FROM `##change` WHERE user_id=? AND status='accepted'")->execute(array($this->user_id)); WT_DB::prepare("UPDATE `##change` SET user_id=? WHERE user_id=?")->execute(array($this->user_id, $this->user_id)); WT_DB::prepare("DELETE `##block_setting` FROM `##block_setting` JOIN `##block` USING (block_id) WHERE user_id=?")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##block` WHERE user_id=?")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##user_gedcom_setting` WHERE user_id=?")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##gedcom_setting` WHERE setting_value=? AND setting_name in ('CONTACT_USER_ID', 'WEBMASTER_USER_ID')")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##user_setting` WHERE user_id=?")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##message` WHERE user_id=?")->execute(array($this->user_id)); WT_DB::prepare("DELETE FROM `##user` WHERE user_id=?")->execute(array($this->user_id)); } /** Validate a supplied password * * @param string $password * * @return bool */ public function checkPassword($password) { $password_hash = WT_DB::prepare( "SELECT password FROM `##user` WHERE user_id = ?" )->execute(array($this->user_id))->fetchOne(); if (password_verify($password, $password_hash)) { if (password_needs_rehash($password_hash, PASSWORD_DEFAULT)) { $this->setPassword($password); } return true; } else { return false; } } // Getters and setters for user attributes public function getUserId() { return $this->user_id; } public function getUserName() { return $this->user_name; } public function setUserName($user_name) { if ($this->user_name !== $user_name) { $this->user_name = $user_name; WT_DB::prepare( "UPDATE `##user` SET user_name = ? WHERE user_id = ?" )->execute(array($user_name, $this->user_id)); } return $this; } public function getRealName() { return $this->real_name; } public function setRealName($real_name) { if ($this->real_name !== $real_name) { $this->real_name = $real_name; WT_DB::prepare( "UPDATE `##user` SET real_name = ? WHERE user_id = ?" )->execute(array($real_name, $this->user_id)); } return $this; } public function getEmail() { return $this->email; } public function setEmail($email) { if ($this->email !== $email) { $this->email = $email; WT_DB::prepare( "UPDATE `##user` SET email = ? WHERE user_id = ?" )->execute(array($email, $this->user_id)); } return $this; } public function setPassword($password) { WT_DB::prepare( "UPDATE `##user` SET password = ? WHERE user_id = ?" )->execute(array(password_hash($password, PASSWORD_DEFAULT), $this->user_id)); return $this; } /** * Fetch a user option/setting from the wt_user_setting table * * Since we'll fetch several settings for each user, and since there aren’t * that many of them, fetch them all in one database query * * @param string $setting_name * @param string|null $default * * @return string|null */ public function getSetting($setting_name, $default = null) { if ($this->settings === null) { if ($this->getUserId()) { $this->settings = WT_DB::prepare( "SELECT SQL_CACHE setting_name, setting_value FROM `##user_setting` WHERE user_id = ?" )->execute(array($this->user_id))->fetchAssoc(); } else { $this->settings = array(); } } if (array_key_exists($setting_name, $this->settings)) { return $this->settings[$setting_name]; } else { return $default; } } /** * Update a setting for the user. * * @param string $setting_name * @param string $setting_value * * @return User */ public function setSetting($setting_name, $setting_value) { if ($setting_value === null) { WT_DB::prepare("DELETE FROM `##user_setting` WHERE user_id=? AND setting_name=?") ->execute(array($this->user_id, $setting_name)); unset($this->settings[$setting_name]); } elseif ($this->settings[$setting_name] !== $setting_value) { WT_DB::prepare("REPLACE INTO `##user_setting` (user_id, setting_name, setting_value) VALUES (?, ?, LEFT(?, 255))") ->execute(array($this->user_id, $setting_name, $setting_value)); $this->settings[$setting_name] = $setting_value; } return $this; } }