xref: /webtrees/app/User.php (revision f7fb7d41913a5b884bc9f0e8ca9c25cb77fb079d)
1a25f0a04SGreg Roach<?php
2a25f0a04SGreg Roach/**
3a25f0a04SGreg Roach * webtrees: online genealogy
46bdf7674SGreg Roach * Copyright (C) 2017 webtrees development team
5a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify
6a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by
7a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or
8a25f0a04SGreg Roach * (at your option) any later version.
9a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful,
10a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
11a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12a25f0a04SGreg Roach * GNU General Public License for more details.
13a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License
14a25f0a04SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
15a25f0a04SGreg Roach */
1676692c8bSGreg Roachnamespace Fisharebest\Webtrees;
17a25f0a04SGreg Roach
1860bc3e3fSGreg Roachuse stdclass;
1960bc3e3fSGreg Roach
20a25f0a04SGreg Roach/**
2176692c8bSGreg Roach * Provide an interface to the wt_user table.
22a25f0a04SGreg Roach */
23a25f0a04SGreg Roachclass User {
24a25f0a04SGreg Roach	/** @var  string The primary key of this user. */
25a25f0a04SGreg Roach	private $user_id;
26a25f0a04SGreg Roach
27a25f0a04SGreg Roach	/** @var  string The login name of this user. */
28a25f0a04SGreg Roach	private $user_name;
29a25f0a04SGreg Roach
30a25f0a04SGreg Roach	/** @var  string The real (display) name of this user. */
31a25f0a04SGreg Roach	private $real_name;
32a25f0a04SGreg Roach
33a25f0a04SGreg Roach	/** @var  string The email address of this user. */
34a25f0a04SGreg Roach	private $email;
35a25f0a04SGreg Roach
3615d603e7SGreg Roach	/** @var string[] Cached copy of the wt_user_setting table. */
3715d603e7SGreg Roach	private $preferences = [];
38a25f0a04SGreg Roach
39a25f0a04SGreg Roach	/** @var  User[] Only fetch users from the database once. */
4013abd6f3SGreg Roach	private static $cache = [];
41a25f0a04SGreg Roach
42a25f0a04SGreg Roach	/**
43*f7fb7d41SGreg Roach	 * Create a new user object from a row in the database.
44*f7fb7d41SGreg Roach	 *
45*f7fb7d41SGreg Roach	 * @param stdclass $user A row from the wt_user table
46*f7fb7d41SGreg Roach	 */
47*f7fb7d41SGreg Roach	public function __construct(stdClass $user) {
48*f7fb7d41SGreg Roach		$this->user_id   = $user->user_id;
49*f7fb7d41SGreg Roach		$this->user_name = $user->user_name;
50*f7fb7d41SGreg Roach		$this->real_name = $user->real_name;
51*f7fb7d41SGreg Roach		$this->email     = $user->email;
52*f7fb7d41SGreg Roach	}
53*f7fb7d41SGreg Roach
54*f7fb7d41SGreg Roach	/**
55*f7fb7d41SGreg Roach	 * Create a new user.
56*f7fb7d41SGreg Roach	 *
57*f7fb7d41SGreg Roach	 * The calling code needs to check for duplicates identifiers before calling
58*f7fb7d41SGreg Roach	 * this function.
59*f7fb7d41SGreg Roach	 *
60*f7fb7d41SGreg Roach	 * @param string $user_name
61*f7fb7d41SGreg Roach	 * @param string $real_name
62*f7fb7d41SGreg Roach	 * @param string $email
63*f7fb7d41SGreg Roach	 * @param string $password
64*f7fb7d41SGreg Roach	 *
65*f7fb7d41SGreg Roach	 * @return User
66*f7fb7d41SGreg Roach	 */
67*f7fb7d41SGreg Roach	public static function create($user_name, $real_name, $email, $password) {
68*f7fb7d41SGreg Roach		Database::prepare(
69*f7fb7d41SGreg Roach			"INSERT INTO `##user` (user_name, real_name, email, password) VALUES (:user_name, :real_name, :email, :password)"
70*f7fb7d41SGreg Roach		)->execute([
71*f7fb7d41SGreg Roach			'user_name' => $user_name,
72*f7fb7d41SGreg Roach			'real_name' => $real_name,
73*f7fb7d41SGreg Roach			'email'     => $email,
74*f7fb7d41SGreg Roach			'password'  => password_hash($password, PASSWORD_DEFAULT),
75*f7fb7d41SGreg Roach		]);
76*f7fb7d41SGreg Roach
77*f7fb7d41SGreg Roach		// Set default blocks for this user
78*f7fb7d41SGreg Roach		$user = self::findByIdentifier($user_name);
79*f7fb7d41SGreg Roach		Database::prepare(
80*f7fb7d41SGreg Roach			"INSERT INTO `##block` (`user_id`, `location`, `block_order`, `module_name`)" .
81*f7fb7d41SGreg Roach			" SELECT :user_id , `location`, `block_order`, `module_name` FROM `##block` WHERE `user_id` = -1"
82*f7fb7d41SGreg Roach		)->execute(['user_id' => $user->getUserId()]);
83*f7fb7d41SGreg Roach
84*f7fb7d41SGreg Roach		return $user;
85*f7fb7d41SGreg Roach	}
86*f7fb7d41SGreg Roach
87*f7fb7d41SGreg Roach	/**
88*f7fb7d41SGreg Roach	 * Delete a user
89*f7fb7d41SGreg Roach	 */
90*f7fb7d41SGreg Roach	public function delete() {
91*f7fb7d41SGreg Roach		// Don't delete the logs.
92*f7fb7d41SGreg Roach		Database::prepare("UPDATE `##log` SET user_id=NULL WHERE user_id =?")->execute([$this->user_id]);
93*f7fb7d41SGreg Roach		// Take over the user’s pending changes. (What else could we do with them?)
94*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##change` WHERE user_id=? AND status='rejected'")->execute([$this->user_id]);
95*f7fb7d41SGreg Roach		Database::prepare("UPDATE `##change` SET user_id=? WHERE user_id=?")->execute([Auth::id(), $this->user_id]);
96*f7fb7d41SGreg Roach		Database::prepare("DELETE `##block_setting` FROM `##block_setting` JOIN `##block` USING (block_id) WHERE user_id=?")->execute([$this->user_id]);
97*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##block` WHERE user_id=?")->execute([$this->user_id]);
98*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user_gedcom_setting` WHERE user_id=?")->execute([$this->user_id]);
99*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##gedcom_setting` WHERE setting_value=? AND setting_name IN ('CONTACT_USER_ID', 'WEBMASTER_USER_ID')")->execute([$this->user_id]);
100*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user_setting` WHERE user_id=?")->execute([$this->user_id]);
101*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##message` WHERE user_id=?")->execute([$this->user_id]);
102*f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user` WHERE user_id=?")->execute([$this->user_id]);
103*f7fb7d41SGreg Roach	}
104*f7fb7d41SGreg Roach
105*f7fb7d41SGreg Roach	/**
106a25f0a04SGreg Roach	 * Find the user with a specified user_id.
107a25f0a04SGreg Roach	 *
108cbc1590aSGreg Roach	 * @param int|null $user_id
109a25f0a04SGreg Roach	 *
110a25f0a04SGreg Roach	 * @return User|null
111a25f0a04SGreg Roach	 */
112a25f0a04SGreg Roach	public static function find($user_id) {
113a25f0a04SGreg Roach		if (!array_key_exists($user_id, self::$cache)) {
114a25f0a04SGreg Roach			$row = Database::prepare(
115a25f0a04SGreg Roach				"SELECT SQL_CACHE user_id, user_name, real_name, email FROM `##user` WHERE user_id = ?"
11613abd6f3SGreg Roach			)->execute([$user_id])->fetchOneRow();
117a25f0a04SGreg Roach			if ($row) {
11806ef8e02SGreg Roach				self::$cache[$user_id] = new self($row);
119a25f0a04SGreg Roach			} else {
120a25f0a04SGreg Roach				self::$cache[$user_id] = null;
121a25f0a04SGreg Roach			}
122a25f0a04SGreg Roach		}
123a25f0a04SGreg Roach
124a25f0a04SGreg Roach		return self::$cache[$user_id];
125a25f0a04SGreg Roach	}
126a25f0a04SGreg Roach
127a25f0a04SGreg Roach	/**
128a982a56eSGreg Roach	 * Find the user with a specified email address.
129a982a56eSGreg Roach	 *
130a982a56eSGreg Roach	 * @param string $email
131a982a56eSGreg Roach	 *
132a982a56eSGreg Roach	 * @return User|null
133a982a56eSGreg Roach	 */
134a982a56eSGreg Roach	public static function findByEmail($email) {
135a982a56eSGreg Roach		$user_id = Database::prepare(
136a982a56eSGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE email = :email"
13713abd6f3SGreg Roach		)->execute([
138a982a56eSGreg Roach			'email' => $email,
13913abd6f3SGreg Roach		])->fetchOne();
140a982a56eSGreg Roach
141a982a56eSGreg Roach		return self::find($user_id);
142a982a56eSGreg Roach	}
143a982a56eSGreg Roach
144a982a56eSGreg Roach	/**
145a982a56eSGreg Roach	 * Find the user with a specified user_name or email address.
146a25f0a04SGreg Roach	 *
147a25f0a04SGreg Roach	 * @param string $identifier
148a25f0a04SGreg Roach	 *
149a25f0a04SGreg Roach	 * @return User|null
150a25f0a04SGreg Roach	 */
151a25f0a04SGreg Roach	public static function findByIdentifier($identifier) {
152a25f0a04SGreg Roach		$user_id = Database::prepare(
153a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE ? IN (user_name, email)"
15413abd6f3SGreg Roach		)->execute([$identifier])->fetchOne();
155a25f0a04SGreg Roach
156a25f0a04SGreg Roach		return self::find($user_id);
157a25f0a04SGreg Roach	}
158a25f0a04SGreg Roach
159a25f0a04SGreg Roach	/**
160a25f0a04SGreg Roach	 * Find the user with a specified genealogy record.
161a25f0a04SGreg Roach	 *
162a25f0a04SGreg Roach	 * @param Individual $individual
163a25f0a04SGreg Roach	 *
164a25f0a04SGreg Roach	 * @return User|null
165a25f0a04SGreg Roach	 */
166*f7fb7d41SGreg Roach	public static function findByIndividual(Individual $individual) {
167a25f0a04SGreg Roach		$user_id = Database::prepare(
168a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id" .
169a25f0a04SGreg Roach			" FROM `##user_gedcom_setting`" .
170a5adda01SGreg Roach			" WHERE gedcom_id = :tree_id AND setting_name = 'gedcomid' AND setting_value = :xref"
17113abd6f3SGreg Roach		)->execute([
172a5adda01SGreg Roach			'tree_id' => $individual->getTree()->getTreeId(),
173cbc1590aSGreg Roach			'xref'    => $individual->getXref(),
17413abd6f3SGreg Roach		])->fetchOne();
175a25f0a04SGreg Roach
176a25f0a04SGreg Roach		return self::find($user_id);
177a25f0a04SGreg Roach	}
178a25f0a04SGreg Roach
179a25f0a04SGreg Roach	/**
180*f7fb7d41SGreg Roach	 * Find the user with a specified user_name.
181*f7fb7d41SGreg Roach	 *
182*f7fb7d41SGreg Roach	 * @param string $user_name
183*f7fb7d41SGreg Roach	 *
184*f7fb7d41SGreg Roach	 * @return User|null
185*f7fb7d41SGreg Roach	 */
186*f7fb7d41SGreg Roach	public static function findByUserName($user_name) {
187*f7fb7d41SGreg Roach		$user_id = Database::prepare(
188*f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE user_name = :user_name"
189*f7fb7d41SGreg Roach		)->execute([
190*f7fb7d41SGreg Roach			'user_name' => $user_name,
191*f7fb7d41SGreg Roach		])->fetchOne();
192*f7fb7d41SGreg Roach
193*f7fb7d41SGreg Roach		return self::find($user_id);
194*f7fb7d41SGreg Roach	}
195*f7fb7d41SGreg Roach
196*f7fb7d41SGreg Roach	/**
197a25f0a04SGreg Roach	 * Find the latest user to register.
198a25f0a04SGreg Roach	 *
199a25f0a04SGreg Roach	 * @return User|null
200a25f0a04SGreg Roach	 */
201a25f0a04SGreg Roach	public static function findLatestToRegister() {
202a25f0a04SGreg Roach		$user_id = Database::prepare(
203a25f0a04SGreg Roach			"SELECT SQL_CACHE u.user_id" .
204a25f0a04SGreg Roach			" FROM `##user` u" .
205a25f0a04SGreg Roach			" LEFT JOIN `##user_setting` us ON (u.user_id=us.user_id AND us.setting_name='reg_timestamp') " .
206a25f0a04SGreg Roach			" ORDER BY us.setting_value DESC LIMIT 1"
207a25f0a04SGreg Roach		)->execute()->fetchOne();
208a25f0a04SGreg Roach
209a25f0a04SGreg Roach		return self::find($user_id);
210a25f0a04SGreg Roach	}
211a25f0a04SGreg Roach
212a25f0a04SGreg Roach	/**
213a25f0a04SGreg Roach	 * Get a list of all users.
214a25f0a04SGreg Roach	 *
215a25f0a04SGreg Roach	 * @return User[]
216a25f0a04SGreg Roach	 */
217a25f0a04SGreg Roach	public static function all() {
218a25f0a04SGreg Roach		$rows = Database::prepare(
219a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
220a25f0a04SGreg Roach			" FROM `##user`" .
221a25f0a04SGreg Roach			" WHERE user_id > 0" .
222*f7fb7d41SGreg Roach			" ORDER BY real_name"
223a25f0a04SGreg Roach		)->fetchAll();
224a25f0a04SGreg Roach
225*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
226a25f0a04SGreg Roach	}
227a25f0a04SGreg Roach
228a25f0a04SGreg Roach	/**
229a25f0a04SGreg Roach	 * Get a list of all administrators.
230a25f0a04SGreg Roach	 *
231a25f0a04SGreg Roach	 * @return User[]
232a25f0a04SGreg Roach	 */
233*f7fb7d41SGreg Roach	public static function administrators() {
234a25f0a04SGreg Roach		$rows = Database::prepare(
235a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
236a25f0a04SGreg Roach			" FROM `##user`" .
237a25f0a04SGreg Roach			" JOIN `##user_setting` USING (user_id)" .
238*f7fb7d41SGreg Roach			" WHERE user_id > 0 AND setting_name = 'canadmin' AND setting_value = '1'" .
239*f7fb7d41SGreg Roach			" ORDER BY real_name"
240a25f0a04SGreg Roach		)->fetchAll();
241a25f0a04SGreg Roach
242*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
243a25f0a04SGreg Roach	}
244a25f0a04SGreg Roach
245a25f0a04SGreg Roach	/** Validate a supplied password
246a25f0a04SGreg Roach	 * @param string $password
247a25f0a04SGreg Roach	 *
248cbc1590aSGreg Roach	 * @return bool
249a25f0a04SGreg Roach	 */
250a25f0a04SGreg Roach	public function checkPassword($password) {
251a25f0a04SGreg Roach		$password_hash = Database::prepare(
252a25f0a04SGreg Roach			"SELECT password FROM `##user` WHERE user_id = ?"
25313abd6f3SGreg Roach		)->execute([$this->user_id])->fetchOne();
254a25f0a04SGreg Roach
255015c99a2SGreg Roach		if (password_verify($password, $password_hash)) {
256015c99a2SGreg Roach			if (password_needs_rehash($password_hash, PASSWORD_DEFAULT)) {
257a25f0a04SGreg Roach				$this->setPassword($password);
258a25f0a04SGreg Roach			}
259cbc1590aSGreg Roach
260a25f0a04SGreg Roach			return true;
261a25f0a04SGreg Roach		} else {
262a25f0a04SGreg Roach			return false;
263a25f0a04SGreg Roach		}
264a25f0a04SGreg Roach	}
265a25f0a04SGreg Roach
266a25f0a04SGreg Roach	/**
267*f7fb7d41SGreg Roach	 * Get a list of all managers.
268*f7fb7d41SGreg Roach	 *
269*f7fb7d41SGreg Roach	 * @return User[]
270*f7fb7d41SGreg Roach	 */
271*f7fb7d41SGreg Roach	public static function managers() {
272*f7fb7d41SGreg Roach		$rows = Database::prepare(
273*f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
274*f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_gedcom_setting` USING (user_id)" .
275*f7fb7d41SGreg Roach			" WHERE setting_name = 'canedit' AND setting_value='admin'" .
276*f7fb7d41SGreg Roach			" GROUP BY user_id, real_name" .
277*f7fb7d41SGreg Roach			" ORDER BY real_name"
278*f7fb7d41SGreg Roach		)->fetchAll();
279*f7fb7d41SGreg Roach
280*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
281*f7fb7d41SGreg Roach	}
282*f7fb7d41SGreg Roach
283*f7fb7d41SGreg Roach	/**
284*f7fb7d41SGreg Roach	 * Get a list of all moderators.
285*f7fb7d41SGreg Roach	 *
286*f7fb7d41SGreg Roach	 * @return User[]
287*f7fb7d41SGreg Roach	 */
288*f7fb7d41SGreg Roach	public static function moderators() {
289*f7fb7d41SGreg Roach		$rows = Database::prepare(
290*f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
291*f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_gedcom_setting` USING (user_id)" .
292*f7fb7d41SGreg Roach			" WHERE setting_name = 'canedit' AND setting_value='accept'" .
293*f7fb7d41SGreg Roach			" GROUP BY user_id, real_name" .
294*f7fb7d41SGreg Roach			" ORDER BY real_name"
295*f7fb7d41SGreg Roach		)->fetchAll();
296*f7fb7d41SGreg Roach
297*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
298*f7fb7d41SGreg Roach	}
299*f7fb7d41SGreg Roach
300*f7fb7d41SGreg Roach	/**
301*f7fb7d41SGreg Roach	 * Get a list of all verified users.
302*f7fb7d41SGreg Roach	 *
303*f7fb7d41SGreg Roach	 * @return User[]
304*f7fb7d41SGreg Roach	 */
305*f7fb7d41SGreg Roach	public static function unapproved() {
306*f7fb7d41SGreg Roach		$rows = Database::prepare(
307*f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
308*f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_setting` USING (user_id)" .
309*f7fb7d41SGreg Roach			" WHERE setting_name = 'verified_by_admin' AND setting_value = '0'" .
310*f7fb7d41SGreg Roach			" ORDER BY real_name"
311*f7fb7d41SGreg Roach		)->fetchAll();
312*f7fb7d41SGreg Roach
313*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
314*f7fb7d41SGreg Roach	}
315*f7fb7d41SGreg Roach
316*f7fb7d41SGreg Roach	/**
317*f7fb7d41SGreg Roach	 * Get a list of all verified users.
318*f7fb7d41SGreg Roach	 *
319*f7fb7d41SGreg Roach	 * @return User[]
320*f7fb7d41SGreg Roach	 */
321*f7fb7d41SGreg Roach	public static function unverified() {
322*f7fb7d41SGreg Roach		$rows = Database::prepare(
323*f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
324*f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_setting` USING (user_id)" .
325*f7fb7d41SGreg Roach			" WHERE setting_name = 'verified' AND setting_value = '0'" .
326*f7fb7d41SGreg Roach			" ORDER BY real_name"
327*f7fb7d41SGreg Roach		)->fetchAll();
328*f7fb7d41SGreg Roach
329*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
330*f7fb7d41SGreg Roach	}
331*f7fb7d41SGreg Roach
332*f7fb7d41SGreg Roach	/**
333*f7fb7d41SGreg Roach	 * Get a list of all users who are currently logged in.
334*f7fb7d41SGreg Roach	 *
335*f7fb7d41SGreg Roach	 * @return User[]
336*f7fb7d41SGreg Roach	 */
337*f7fb7d41SGreg Roach	public static function allLoggedIn() {
338*f7fb7d41SGreg Roach		$rows = Database::prepare(
339*f7fb7d41SGreg Roach			"SELECT SQL_NO_CACHE DISTINCT user_id, user_name, real_name, email" .
340*f7fb7d41SGreg Roach			" FROM `##user`" .
341*f7fb7d41SGreg Roach			" JOIN `##session` USING (user_id)"
342*f7fb7d41SGreg Roach		)->fetchAll();
343*f7fb7d41SGreg Roach
344*f7fb7d41SGreg Roach		return array_map(function($row) { return new static($row); }, $rows);
345*f7fb7d41SGreg Roach	}
346*f7fb7d41SGreg Roach
347*f7fb7d41SGreg Roach	/**
348a25f0a04SGreg Roach	 * Get the numeric ID for this user.
349a25f0a04SGreg Roach	 *
350a25f0a04SGreg Roach	 * @return string
351a25f0a04SGreg Roach	 */
352a25f0a04SGreg Roach	public function getUserId() {
353a25f0a04SGreg Roach		return $this->user_id;
354a25f0a04SGreg Roach	}
355a25f0a04SGreg Roach
356a25f0a04SGreg Roach	/**
357a25f0a04SGreg Roach	 * Get the login name for this user.
358a25f0a04SGreg Roach	 *
359a25f0a04SGreg Roach	 * @return string
360a25f0a04SGreg Roach	 */
361a25f0a04SGreg Roach	public function getUserName() {
362a25f0a04SGreg Roach		return $this->user_name;
363a25f0a04SGreg Roach	}
364a25f0a04SGreg Roach
365a25f0a04SGreg Roach	/**
366a25f0a04SGreg Roach	 * Set the login name for this user.
367a25f0a04SGreg Roach	 *
368a25f0a04SGreg Roach	 * @param string $user_name
369a25f0a04SGreg Roach	 *
370a25f0a04SGreg Roach	 * @return $this
371a25f0a04SGreg Roach	 */
372a25f0a04SGreg Roach	public function setUserName($user_name) {
373a25f0a04SGreg Roach		if ($this->user_name !== $user_name) {
374a25f0a04SGreg Roach			$this->user_name = $user_name;
375a25f0a04SGreg Roach			Database::prepare(
376a25f0a04SGreg Roach				"UPDATE `##user` SET user_name = ? WHERE user_id = ?"
37713abd6f3SGreg Roach			)->execute([$user_name, $this->user_id]);
378a25f0a04SGreg Roach		}
379a25f0a04SGreg Roach
380a25f0a04SGreg Roach		return $this;
381a25f0a04SGreg Roach	}
382a25f0a04SGreg Roach
383a25f0a04SGreg Roach	/**
384a25f0a04SGreg Roach	 * Get the real name of this user.
385a25f0a04SGreg Roach	 *
386a25f0a04SGreg Roach	 * @return string
387a25f0a04SGreg Roach	 */
388a25f0a04SGreg Roach	public function getRealName() {
389a25f0a04SGreg Roach		return $this->real_name;
390a25f0a04SGreg Roach	}
391a25f0a04SGreg Roach
392a25f0a04SGreg Roach	/**
393524c0fabSGreg Roach	 * Get the real name of this user, for display on screen.
394524c0fabSGreg Roach	 *
395524c0fabSGreg Roach	 * @return string
396524c0fabSGreg Roach	 */
397524c0fabSGreg Roach	public function getRealNameHtml() {
398cc5ab399SGreg Roach		return '<span dir="auto">' . Html::escape($this->real_name) . '</span>';
399524c0fabSGreg Roach	}
400524c0fabSGreg Roach
401524c0fabSGreg Roach	/**
402a25f0a04SGreg Roach	 * Set the real name of this user.
403a25f0a04SGreg Roach	 *
404a25f0a04SGreg Roach	 * @param string $real_name
405a25f0a04SGreg Roach	 *
406a25f0a04SGreg Roach	 * @return User
407a25f0a04SGreg Roach	 */
408a25f0a04SGreg Roach	public function setRealName($real_name) {
409a25f0a04SGreg Roach		if ($this->real_name !== $real_name) {
410a25f0a04SGreg Roach			$this->real_name = $real_name;
411a25f0a04SGreg Roach			Database::prepare(
412a25f0a04SGreg Roach				"UPDATE `##user` SET real_name = ? WHERE user_id = ?"
41313abd6f3SGreg Roach			)->execute([$real_name, $this->user_id]);
414a25f0a04SGreg Roach		}
415a25f0a04SGreg Roach
416a25f0a04SGreg Roach		return $this;
417a25f0a04SGreg Roach	}
418a25f0a04SGreg Roach
419a25f0a04SGreg Roach	/**
420a25f0a04SGreg Roach	 * Get the email address of this user.
421a25f0a04SGreg Roach	 *
422a25f0a04SGreg Roach	 * @return string
423a25f0a04SGreg Roach	 */
424a25f0a04SGreg Roach	public function getEmail() {
425a25f0a04SGreg Roach		return $this->email;
426a25f0a04SGreg Roach	}
427a25f0a04SGreg Roach
428a25f0a04SGreg Roach	/**
429a25f0a04SGreg Roach	 * Set the email address of this user.
430a25f0a04SGreg Roach	 *
431a25f0a04SGreg Roach	 * @param string $email
432a25f0a04SGreg Roach	 *
433a25f0a04SGreg Roach	 * @return User
434a25f0a04SGreg Roach	 */
435a25f0a04SGreg Roach	public function setEmail($email) {
436a25f0a04SGreg Roach		if ($this->email !== $email) {
437a25f0a04SGreg Roach			$this->email = $email;
438a25f0a04SGreg Roach			Database::prepare(
439a25f0a04SGreg Roach				"UPDATE `##user` SET email = ? WHERE user_id = ?"
44013abd6f3SGreg Roach			)->execute([$email, $this->user_id]);
441a25f0a04SGreg Roach		}
442a25f0a04SGreg Roach
443a25f0a04SGreg Roach		return $this;
444a25f0a04SGreg Roach	}
445a25f0a04SGreg Roach
446a25f0a04SGreg Roach	/**
447a25f0a04SGreg Roach	 * Set the password of this user.
448a25f0a04SGreg Roach	 *
449a25f0a04SGreg Roach	 * @param string $password
450a25f0a04SGreg Roach	 *
451a25f0a04SGreg Roach	 * @return User
452a25f0a04SGreg Roach	 */
453a25f0a04SGreg Roach	public function setPassword($password) {
454a25f0a04SGreg Roach		Database::prepare(
455015c99a2SGreg Roach			"UPDATE `##user` SET password = :password WHERE user_id = :user_id"
456015c99a2SGreg Roach		)->execute([
457015c99a2SGreg Roach			'password' => password_hash($password, PASSWORD_DEFAULT),
458015c99a2SGreg Roach			'user_id'  => $this->user_id,
459015c99a2SGreg Roach		]);
460a25f0a04SGreg Roach
461a25f0a04SGreg Roach		return $this;
462a25f0a04SGreg Roach	}
463a25f0a04SGreg Roach
464a25f0a04SGreg Roach	/**
465a25f0a04SGreg Roach	 * Fetch a user option/setting from the wt_user_setting table.
466a25f0a04SGreg Roach	 *
467a25f0a04SGreg Roach	 * Since we'll fetch several settings for each user, and since there aren’t
468a25f0a04SGreg Roach	 * that many of them, fetch them all in one database query
469a25f0a04SGreg Roach	 *
470a25f0a04SGreg Roach	 * @param string $setting_name
47115d603e7SGreg Roach	 * @param string $default
472a25f0a04SGreg Roach	 *
47315d603e7SGreg Roach	 * @return string
474a25f0a04SGreg Roach	 */
47515d603e7SGreg Roach	public function getPreference($setting_name, $default = '') {
47615d603e7SGreg Roach		if (empty($this->preferences) && $this->user_id !== null) {
477a25f0a04SGreg Roach			$this->preferences = Database::prepare(
47815d603e7SGreg Roach				"SELECT SQL_CACHE setting_name, setting_value" .
47915d603e7SGreg Roach				" FROM `##user_setting`" .
48015d603e7SGreg Roach				" WHERE user_id = :user_id"
48115d603e7SGreg Roach			)->execute([
48215d603e7SGreg Roach				'user_id' => $this->user_id,
48315d603e7SGreg Roach			])->fetchAssoc();
484a25f0a04SGreg Roach		}
485a25f0a04SGreg Roach
48615d603e7SGreg Roach		if (!array_key_exists($setting_name, $this->preferences)) {
48715d603e7SGreg Roach			$this->preferences[$setting_name] = $default;
488a25f0a04SGreg Roach		}
48915d603e7SGreg Roach
49015d603e7SGreg Roach		return $this->preferences[$setting_name];
491a25f0a04SGreg Roach	}
492a25f0a04SGreg Roach
493a25f0a04SGreg Roach	/**
494a25f0a04SGreg Roach	 * Update a setting for the user.
495a25f0a04SGreg Roach	 *
496a25f0a04SGreg Roach	 * @param string $setting_name
497a25f0a04SGreg Roach	 * @param string $setting_value
498a25f0a04SGreg Roach	 *
499a25f0a04SGreg Roach	 * @return User
500a25f0a04SGreg Roach	 */
501a25f0a04SGreg Roach	public function setPreference($setting_name, $setting_value) {
502a25f0a04SGreg Roach		if ($this->user_id && $this->getPreference($setting_name) !== $setting_value) {
503a25f0a04SGreg Roach			Database::prepare("REPLACE INTO `##user_setting` (user_id, setting_name, setting_value) VALUES (?, ?, LEFT(?, 255))")
50413abd6f3SGreg Roach				->execute([$this->user_id, $setting_name, $setting_value]);
50515d603e7SGreg Roach
506a25f0a04SGreg Roach			$this->preferences[$setting_name] = $setting_value;
507a25f0a04SGreg Roach		}
508a25f0a04SGreg Roach
509a25f0a04SGreg Roach		return $this;
510a25f0a04SGreg Roach	}
511a25f0a04SGreg Roach}
512