xref: /webtrees/app/User.php (revision c04dd3c17ac656dcbbcfb7768a9a2f58fa0a3e54)
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 */
16*c04dd3c1SGreg Roachdeclare(strict_types=1);
17*c04dd3c1SGreg Roach
1876692c8bSGreg Roachnamespace Fisharebest\Webtrees;
19a25f0a04SGreg Roach
2060bc3e3fSGreg Roachuse stdclass;
2160bc3e3fSGreg Roach
22a25f0a04SGreg Roach/**
2376692c8bSGreg Roach * Provide an interface to the wt_user table.
24a25f0a04SGreg Roach */
25a25f0a04SGreg Roachclass User {
26*c04dd3c1SGreg Roach	/** @var  int The primary key of this user. */
27a25f0a04SGreg Roach	private $user_id;
28a25f0a04SGreg Roach
29a25f0a04SGreg Roach	/** @var  string The login name of this user. */
30a25f0a04SGreg Roach	private $user_name;
31a25f0a04SGreg Roach
32a25f0a04SGreg Roach	/** @var  string The real (display) name of this user. */
33a25f0a04SGreg Roach	private $real_name;
34a25f0a04SGreg Roach
35a25f0a04SGreg Roach	/** @var  string The email address of this user. */
36a25f0a04SGreg Roach	private $email;
37a25f0a04SGreg Roach
3815d603e7SGreg Roach	/** @var string[] Cached copy of the wt_user_setting table. */
3915d603e7SGreg Roach	private $preferences = [];
40a25f0a04SGreg Roach
41a25f0a04SGreg Roach	/** @var  User[] Only fetch users from the database once. */
4213abd6f3SGreg Roach	private static $cache = [];
43a25f0a04SGreg Roach
44a25f0a04SGreg Roach	/**
45f7fb7d41SGreg Roach	 * Create a new user object from a row in the database.
46f7fb7d41SGreg Roach	 *
47f7fb7d41SGreg Roach	 * @param stdclass $user A row from the wt_user table
48f7fb7d41SGreg Roach	 */
49f7fb7d41SGreg Roach	public function __construct(stdClass $user) {
50*c04dd3c1SGreg Roach		$this->user_id   = (int) $user->user_id;
51f7fb7d41SGreg Roach		$this->user_name = $user->user_name;
52f7fb7d41SGreg Roach		$this->real_name = $user->real_name;
53f7fb7d41SGreg Roach		$this->email     = $user->email;
54f7fb7d41SGreg Roach	}
55f7fb7d41SGreg Roach
56f7fb7d41SGreg Roach	/**
57f7fb7d41SGreg Roach	 * Create a new user.
58f7fb7d41SGreg Roach	 *
59f7fb7d41SGreg Roach	 * The calling code needs to check for duplicates identifiers before calling
60f7fb7d41SGreg Roach	 * this function.
61f7fb7d41SGreg Roach	 *
62f7fb7d41SGreg Roach	 * @param string $user_name
63f7fb7d41SGreg Roach	 * @param string $real_name
64f7fb7d41SGreg Roach	 * @param string $email
65f7fb7d41SGreg Roach	 * @param string $password
66f7fb7d41SGreg Roach	 *
67f7fb7d41SGreg Roach	 * @return User
68f7fb7d41SGreg Roach	 */
69f7fb7d41SGreg Roach	public static function create($user_name, $real_name, $email, $password) {
70f7fb7d41SGreg Roach		Database::prepare(
71f7fb7d41SGreg Roach			"INSERT INTO `##user` (user_name, real_name, email, password) VALUES (:user_name, :real_name, :email, :password)"
72f7fb7d41SGreg Roach		)->execute([
73f7fb7d41SGreg Roach			'user_name' => $user_name,
74f7fb7d41SGreg Roach			'real_name' => $real_name,
75f7fb7d41SGreg Roach			'email'     => $email,
76f7fb7d41SGreg Roach			'password'  => password_hash($password, PASSWORD_DEFAULT),
77f7fb7d41SGreg Roach		]);
78f7fb7d41SGreg Roach
79f7fb7d41SGreg Roach		// Set default blocks for this user
80f7fb7d41SGreg Roach		$user = self::findByIdentifier($user_name);
81f7fb7d41SGreg Roach		Database::prepare(
82f7fb7d41SGreg Roach			"INSERT INTO `##block` (`user_id`, `location`, `block_order`, `module_name`)" .
83f7fb7d41SGreg Roach			" SELECT :user_id , `location`, `block_order`, `module_name` FROM `##block` WHERE `user_id` = -1"
84f7fb7d41SGreg Roach		)->execute(['user_id' => $user->getUserId()]);
85f7fb7d41SGreg Roach
86f7fb7d41SGreg Roach		return $user;
87f7fb7d41SGreg Roach	}
88f7fb7d41SGreg Roach
89f7fb7d41SGreg Roach	/**
90f7fb7d41SGreg Roach	 * Delete a user
91f7fb7d41SGreg Roach	 */
92f7fb7d41SGreg Roach	public function delete() {
93f7fb7d41SGreg Roach		// Don't delete the logs.
94f7fb7d41SGreg Roach		Database::prepare("UPDATE `##log` SET user_id=NULL WHERE user_id =?")->execute([$this->user_id]);
95f7fb7d41SGreg Roach		// Take over the user’s pending changes. (What else could we do with them?)
96f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##change` WHERE user_id=? AND status='rejected'")->execute([$this->user_id]);
97f7fb7d41SGreg Roach		Database::prepare("UPDATE `##change` SET user_id=? WHERE user_id=?")->execute([Auth::id(), $this->user_id]);
98f7fb7d41SGreg Roach		Database::prepare("DELETE `##block_setting` FROM `##block_setting` JOIN `##block` USING (block_id) WHERE user_id=?")->execute([$this->user_id]);
99f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##block` WHERE user_id=?")->execute([$this->user_id]);
100f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user_gedcom_setting` WHERE user_id=?")->execute([$this->user_id]);
101f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##gedcom_setting` WHERE setting_value=? AND setting_name IN ('CONTACT_USER_ID', 'WEBMASTER_USER_ID')")->execute([$this->user_id]);
102f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user_setting` WHERE user_id=?")->execute([$this->user_id]);
103f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##message` WHERE user_id=?")->execute([$this->user_id]);
104f7fb7d41SGreg Roach		Database::prepare("DELETE FROM `##user` WHERE user_id=?")->execute([$this->user_id]);
105f7fb7d41SGreg Roach	}
106f7fb7d41SGreg Roach
107f7fb7d41SGreg Roach	/**
108a25f0a04SGreg Roach	 * Find the user with a specified user_id.
109a25f0a04SGreg Roach	 *
110cbc1590aSGreg Roach	 * @param int|null $user_id
111a25f0a04SGreg Roach	 *
112a25f0a04SGreg Roach	 * @return User|null
113a25f0a04SGreg Roach	 */
114a25f0a04SGreg Roach	public static function find($user_id) {
115a25f0a04SGreg Roach		if (!array_key_exists($user_id, self::$cache)) {
116a25f0a04SGreg Roach			$row = Database::prepare(
117a25f0a04SGreg Roach				"SELECT SQL_CACHE user_id, user_name, real_name, email FROM `##user` WHERE user_id = ?"
11813abd6f3SGreg Roach			)->execute([$user_id])->fetchOneRow();
119a25f0a04SGreg Roach			if ($row) {
12006ef8e02SGreg Roach				self::$cache[$user_id] = new self($row);
121a25f0a04SGreg Roach			} else {
122a25f0a04SGreg Roach				self::$cache[$user_id] = null;
123a25f0a04SGreg Roach			}
124a25f0a04SGreg Roach		}
125a25f0a04SGreg Roach
126a25f0a04SGreg Roach		return self::$cache[$user_id];
127a25f0a04SGreg Roach	}
128a25f0a04SGreg Roach
129a25f0a04SGreg Roach	/**
130a982a56eSGreg Roach	 * Find the user with a specified email address.
131a982a56eSGreg Roach	 *
132a982a56eSGreg Roach	 * @param string $email
133a982a56eSGreg Roach	 *
134a982a56eSGreg Roach	 * @return User|null
135a982a56eSGreg Roach	 */
136a982a56eSGreg Roach	public static function findByEmail($email) {
137a982a56eSGreg Roach		$user_id = Database::prepare(
138a982a56eSGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE email = :email"
13913abd6f3SGreg Roach		)->execute([
140a982a56eSGreg Roach			'email' => $email,
14113abd6f3SGreg Roach		])->fetchOne();
142a982a56eSGreg Roach
143a982a56eSGreg Roach		return self::find($user_id);
144a982a56eSGreg Roach	}
145a982a56eSGreg Roach
146a982a56eSGreg Roach	/**
147a982a56eSGreg Roach	 * Find the user with a specified user_name or email address.
148a25f0a04SGreg Roach	 *
149a25f0a04SGreg Roach	 * @param string $identifier
150a25f0a04SGreg Roach	 *
151a25f0a04SGreg Roach	 * @return User|null
152a25f0a04SGreg Roach	 */
153a25f0a04SGreg Roach	public static function findByIdentifier($identifier) {
154a25f0a04SGreg Roach		$user_id = Database::prepare(
155a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE ? IN (user_name, email)"
15613abd6f3SGreg Roach		)->execute([$identifier])->fetchOne();
157a25f0a04SGreg Roach
158a25f0a04SGreg Roach		return self::find($user_id);
159a25f0a04SGreg Roach	}
160a25f0a04SGreg Roach
161a25f0a04SGreg Roach	/**
162a25f0a04SGreg Roach	 * Find the user with a specified genealogy record.
163a25f0a04SGreg Roach	 *
164a25f0a04SGreg Roach	 * @param Individual $individual
165a25f0a04SGreg Roach	 *
166a25f0a04SGreg Roach	 * @return User|null
167a25f0a04SGreg Roach	 */
168f7fb7d41SGreg Roach	public static function findByIndividual(Individual $individual) {
169a25f0a04SGreg Roach		$user_id = Database::prepare(
170a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id" .
171a25f0a04SGreg Roach			" FROM `##user_gedcom_setting`" .
172a5adda01SGreg Roach			" WHERE gedcom_id = :tree_id AND setting_name = 'gedcomid' AND setting_value = :xref"
17313abd6f3SGreg Roach		)->execute([
174a5adda01SGreg Roach			'tree_id' => $individual->getTree()->getTreeId(),
175cbc1590aSGreg Roach			'xref'    => $individual->getXref(),
17613abd6f3SGreg Roach		])->fetchOne();
177a25f0a04SGreg Roach
178a25f0a04SGreg Roach		return self::find($user_id);
179a25f0a04SGreg Roach	}
180a25f0a04SGreg Roach
181a25f0a04SGreg Roach	/**
182f7fb7d41SGreg Roach	 * Find the user with a specified user_name.
183f7fb7d41SGreg Roach	 *
184f7fb7d41SGreg Roach	 * @param string $user_name
185f7fb7d41SGreg Roach	 *
186f7fb7d41SGreg Roach	 * @return User|null
187f7fb7d41SGreg Roach	 */
188f7fb7d41SGreg Roach	public static function findByUserName($user_name) {
189f7fb7d41SGreg Roach		$user_id = Database::prepare(
190f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id FROM `##user` WHERE user_name = :user_name"
191f7fb7d41SGreg Roach		)->execute([
192f7fb7d41SGreg Roach			'user_name' => $user_name,
193f7fb7d41SGreg Roach		])->fetchOne();
194f7fb7d41SGreg Roach
195f7fb7d41SGreg Roach		return self::find($user_id);
196f7fb7d41SGreg Roach	}
197f7fb7d41SGreg Roach
198f7fb7d41SGreg Roach	/**
199a25f0a04SGreg Roach	 * Find the latest user to register.
200a25f0a04SGreg Roach	 *
201a25f0a04SGreg Roach	 * @return User|null
202a25f0a04SGreg Roach	 */
203a25f0a04SGreg Roach	public static function findLatestToRegister() {
204a25f0a04SGreg Roach		$user_id = Database::prepare(
205a25f0a04SGreg Roach			"SELECT SQL_CACHE u.user_id" .
206a25f0a04SGreg Roach			" FROM `##user` u" .
207a25f0a04SGreg Roach			" LEFT JOIN `##user_setting` us ON (u.user_id=us.user_id AND us.setting_name='reg_timestamp') " .
208a25f0a04SGreg Roach			" ORDER BY us.setting_value DESC LIMIT 1"
209a25f0a04SGreg Roach		)->execute()->fetchOne();
210a25f0a04SGreg Roach
211a25f0a04SGreg Roach		return self::find($user_id);
212a25f0a04SGreg Roach	}
213a25f0a04SGreg Roach
214a25f0a04SGreg Roach	/**
215a25f0a04SGreg Roach	 * Get a list of all users.
216a25f0a04SGreg Roach	 *
217a25f0a04SGreg Roach	 * @return User[]
218a25f0a04SGreg Roach	 */
219a25f0a04SGreg Roach	public static function all() {
220a25f0a04SGreg Roach		$rows = Database::prepare(
221a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
222a25f0a04SGreg Roach			" FROM `##user`" .
223a25f0a04SGreg Roach			" WHERE user_id > 0" .
224f7fb7d41SGreg Roach			" ORDER BY real_name"
225a25f0a04SGreg Roach		)->fetchAll();
226a25f0a04SGreg Roach
2278d68cabeSGreg Roach		return array_map(function($row) {
2288d68cabeSGreg Roach			return new static($row);
2298d68cabeSGreg Roach		}, $rows);
230a25f0a04SGreg Roach	}
231a25f0a04SGreg Roach
232a25f0a04SGreg Roach	/**
233a25f0a04SGreg Roach	 * Get a list of all administrators.
234a25f0a04SGreg Roach	 *
235a25f0a04SGreg Roach	 * @return User[]
236a25f0a04SGreg Roach	 */
237f7fb7d41SGreg Roach	public static function administrators() {
238a25f0a04SGreg Roach		$rows = Database::prepare(
239a25f0a04SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
240a25f0a04SGreg Roach			" FROM `##user`" .
241a25f0a04SGreg Roach			" JOIN `##user_setting` USING (user_id)" .
242f7fb7d41SGreg Roach			" WHERE user_id > 0 AND setting_name = 'canadmin' AND setting_value = '1'" .
243f7fb7d41SGreg Roach			" ORDER BY real_name"
244a25f0a04SGreg Roach		)->fetchAll();
245a25f0a04SGreg Roach
2468d68cabeSGreg Roach		return array_map(function($row) {
2478d68cabeSGreg Roach			return new static($row);
2488d68cabeSGreg Roach		}, $rows);
249a25f0a04SGreg Roach	}
250a25f0a04SGreg Roach
251a25f0a04SGreg Roach	/** Validate a supplied password
252a25f0a04SGreg Roach	 * @param string $password
253a25f0a04SGreg Roach	 *
254cbc1590aSGreg Roach	 * @return bool
255a25f0a04SGreg Roach	 */
256a25f0a04SGreg Roach	public function checkPassword($password) {
257a25f0a04SGreg Roach		$password_hash = Database::prepare(
258a25f0a04SGreg Roach			"SELECT password FROM `##user` WHERE user_id = ?"
25913abd6f3SGreg Roach		)->execute([$this->user_id])->fetchOne();
260a25f0a04SGreg Roach
261015c99a2SGreg Roach		if (password_verify($password, $password_hash)) {
262015c99a2SGreg Roach			if (password_needs_rehash($password_hash, PASSWORD_DEFAULT)) {
263a25f0a04SGreg Roach				$this->setPassword($password);
264a25f0a04SGreg Roach			}
265cbc1590aSGreg Roach
266a25f0a04SGreg Roach			return true;
267a25f0a04SGreg Roach		} else {
268a25f0a04SGreg Roach			return false;
269a25f0a04SGreg Roach		}
270a25f0a04SGreg Roach	}
271a25f0a04SGreg Roach
272a25f0a04SGreg Roach	/**
273f7fb7d41SGreg Roach	 * Get a list of all managers.
274f7fb7d41SGreg Roach	 *
275f7fb7d41SGreg Roach	 * @return User[]
276f7fb7d41SGreg Roach	 */
277f7fb7d41SGreg Roach	public static function managers() {
278f7fb7d41SGreg Roach		$rows = Database::prepare(
279f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
280f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_gedcom_setting` USING (user_id)" .
281f7fb7d41SGreg Roach			" WHERE setting_name = 'canedit' AND setting_value='admin'" .
282f7fb7d41SGreg Roach			" GROUP BY user_id, real_name" .
283f7fb7d41SGreg Roach			" ORDER BY real_name"
284f7fb7d41SGreg Roach		)->fetchAll();
285f7fb7d41SGreg Roach
2868d68cabeSGreg Roach		return array_map(function($row) {
2878d68cabeSGreg Roach			return new static($row);
2888d68cabeSGreg Roach		}, $rows);
289f7fb7d41SGreg Roach	}
290f7fb7d41SGreg Roach
291f7fb7d41SGreg Roach	/**
292f7fb7d41SGreg Roach	 * Get a list of all moderators.
293f7fb7d41SGreg Roach	 *
294f7fb7d41SGreg Roach	 * @return User[]
295f7fb7d41SGreg Roach	 */
296f7fb7d41SGreg Roach	public static function moderators() {
297f7fb7d41SGreg Roach		$rows = Database::prepare(
298f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
299f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_gedcom_setting` USING (user_id)" .
300f7fb7d41SGreg Roach			" WHERE setting_name = 'canedit' AND setting_value='accept'" .
301f7fb7d41SGreg Roach			" GROUP BY user_id, real_name" .
302f7fb7d41SGreg Roach			" ORDER BY real_name"
303f7fb7d41SGreg Roach		)->fetchAll();
304f7fb7d41SGreg Roach
3058d68cabeSGreg Roach		return array_map(function($row) {
3068d68cabeSGreg Roach			return new static($row);
3078d68cabeSGreg Roach		}, $rows);
308f7fb7d41SGreg Roach	}
309f7fb7d41SGreg Roach
310f7fb7d41SGreg Roach	/**
311f7fb7d41SGreg Roach	 * Get a list of all verified users.
312f7fb7d41SGreg Roach	 *
313f7fb7d41SGreg Roach	 * @return User[]
314f7fb7d41SGreg Roach	 */
315f7fb7d41SGreg Roach	public static function unapproved() {
316f7fb7d41SGreg Roach		$rows = Database::prepare(
317f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
318f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_setting` USING (user_id)" .
319f7fb7d41SGreg Roach			" WHERE setting_name = 'verified_by_admin' AND setting_value = '0'" .
320f7fb7d41SGreg Roach			" ORDER BY real_name"
321f7fb7d41SGreg Roach		)->fetchAll();
322f7fb7d41SGreg Roach
3238d68cabeSGreg Roach		return array_map(function($row) {
3248d68cabeSGreg Roach			return new static($row);
3258d68cabeSGreg Roach		}, $rows);
326f7fb7d41SGreg Roach	}
327f7fb7d41SGreg Roach
328f7fb7d41SGreg Roach	/**
329f7fb7d41SGreg Roach	 * Get a list of all verified users.
330f7fb7d41SGreg Roach	 *
331f7fb7d41SGreg Roach	 * @return User[]
332f7fb7d41SGreg Roach	 */
333f7fb7d41SGreg Roach	public static function unverified() {
334f7fb7d41SGreg Roach		$rows = Database::prepare(
335f7fb7d41SGreg Roach			"SELECT SQL_CACHE user_id, user_name, real_name, email" .
336f7fb7d41SGreg Roach			" FROM `##user` JOIN `##user_setting` USING (user_id)" .
337f7fb7d41SGreg Roach			" WHERE setting_name = 'verified' AND setting_value = '0'" .
338f7fb7d41SGreg Roach			" ORDER BY real_name"
339f7fb7d41SGreg Roach		)->fetchAll();
340f7fb7d41SGreg Roach
3418d68cabeSGreg Roach		return array_map(function($row) {
3428d68cabeSGreg Roach			return new static($row);
3438d68cabeSGreg Roach		}, $rows);
344f7fb7d41SGreg Roach	}
345f7fb7d41SGreg Roach
346f7fb7d41SGreg Roach	/**
347f7fb7d41SGreg Roach	 * Get a list of all users who are currently logged in.
348f7fb7d41SGreg Roach	 *
349f7fb7d41SGreg Roach	 * @return User[]
350f7fb7d41SGreg Roach	 */
351f7fb7d41SGreg Roach	public static function allLoggedIn() {
352f7fb7d41SGreg Roach		$rows = Database::prepare(
353f7fb7d41SGreg Roach			"SELECT SQL_NO_CACHE DISTINCT user_id, user_name, real_name, email" .
354f7fb7d41SGreg Roach			" FROM `##user`" .
355f7fb7d41SGreg Roach			" JOIN `##session` USING (user_id)"
356f7fb7d41SGreg Roach		)->fetchAll();
357f7fb7d41SGreg Roach
3588d68cabeSGreg Roach		return array_map(function($row) {
3598d68cabeSGreg Roach			return new static($row);
3608d68cabeSGreg Roach		}, $rows);
361f7fb7d41SGreg Roach	}
362f7fb7d41SGreg Roach
363f7fb7d41SGreg Roach	/**
364a25f0a04SGreg Roach	 * Get the numeric ID for this user.
365a25f0a04SGreg Roach	 *
366*c04dd3c1SGreg Roach	 * @return int
367a25f0a04SGreg Roach	 */
368*c04dd3c1SGreg Roach	public function getUserId(): int {
369a25f0a04SGreg Roach		return $this->user_id;
370a25f0a04SGreg Roach	}
371a25f0a04SGreg Roach
372a25f0a04SGreg Roach	/**
373a25f0a04SGreg Roach	 * Get the login name for this user.
374a25f0a04SGreg Roach	 *
375a25f0a04SGreg Roach	 * @return string
376a25f0a04SGreg Roach	 */
377a25f0a04SGreg Roach	public function getUserName() {
378a25f0a04SGreg Roach		return $this->user_name;
379a25f0a04SGreg Roach	}
380a25f0a04SGreg Roach
381a25f0a04SGreg Roach	/**
382a25f0a04SGreg Roach	 * Set the login name for this user.
383a25f0a04SGreg Roach	 *
384a25f0a04SGreg Roach	 * @param string $user_name
385a25f0a04SGreg Roach	 *
386a25f0a04SGreg Roach	 * @return $this
387a25f0a04SGreg Roach	 */
388a25f0a04SGreg Roach	public function setUserName($user_name) {
389a25f0a04SGreg Roach		if ($this->user_name !== $user_name) {
390a25f0a04SGreg Roach			$this->user_name = $user_name;
391a25f0a04SGreg Roach			Database::prepare(
392a25f0a04SGreg Roach				"UPDATE `##user` SET user_name = ? WHERE user_id = ?"
39313abd6f3SGreg Roach			)->execute([$user_name, $this->user_id]);
394a25f0a04SGreg Roach		}
395a25f0a04SGreg Roach
396a25f0a04SGreg Roach		return $this;
397a25f0a04SGreg Roach	}
398a25f0a04SGreg Roach
399a25f0a04SGreg Roach	/**
400a25f0a04SGreg Roach	 * Get the real name of this user.
401a25f0a04SGreg Roach	 *
402a25f0a04SGreg Roach	 * @return string
403a25f0a04SGreg Roach	 */
404a25f0a04SGreg Roach	public function getRealName() {
405a25f0a04SGreg Roach		return $this->real_name;
406a25f0a04SGreg Roach	}
407a25f0a04SGreg Roach
408a25f0a04SGreg Roach	/**
409524c0fabSGreg Roach	 * Get the real name of this user, for display on screen.
410524c0fabSGreg Roach	 *
411524c0fabSGreg Roach	 * @return string
412524c0fabSGreg Roach	 */
413524c0fabSGreg Roach	public function getRealNameHtml() {
414cc5ab399SGreg Roach		return '<span dir="auto">' . Html::escape($this->real_name) . '</span>';
415524c0fabSGreg Roach	}
416524c0fabSGreg Roach
417524c0fabSGreg Roach	/**
418a25f0a04SGreg Roach	 * Set the real name of this user.
419a25f0a04SGreg Roach	 *
420a25f0a04SGreg Roach	 * @param string $real_name
421a25f0a04SGreg Roach	 *
422a25f0a04SGreg Roach	 * @return User
423a25f0a04SGreg Roach	 */
424a25f0a04SGreg Roach	public function setRealName($real_name) {
425a25f0a04SGreg Roach		if ($this->real_name !== $real_name) {
426a25f0a04SGreg Roach			$this->real_name = $real_name;
427a25f0a04SGreg Roach			Database::prepare(
428a25f0a04SGreg Roach				"UPDATE `##user` SET real_name = ? WHERE user_id = ?"
42913abd6f3SGreg Roach			)->execute([$real_name, $this->user_id]);
430a25f0a04SGreg Roach		}
431a25f0a04SGreg Roach
432a25f0a04SGreg Roach		return $this;
433a25f0a04SGreg Roach	}
434a25f0a04SGreg Roach
435a25f0a04SGreg Roach	/**
436a25f0a04SGreg Roach	 * Get the email address of this user.
437a25f0a04SGreg Roach	 *
438a25f0a04SGreg Roach	 * @return string
439a25f0a04SGreg Roach	 */
440a25f0a04SGreg Roach	public function getEmail() {
441a25f0a04SGreg Roach		return $this->email;
442a25f0a04SGreg Roach	}
443a25f0a04SGreg Roach
444a25f0a04SGreg Roach	/**
445a25f0a04SGreg Roach	 * Set the email address of this user.
446a25f0a04SGreg Roach	 *
447a25f0a04SGreg Roach	 * @param string $email
448a25f0a04SGreg Roach	 *
449a25f0a04SGreg Roach	 * @return User
450a25f0a04SGreg Roach	 */
451a25f0a04SGreg Roach	public function setEmail($email) {
452a25f0a04SGreg Roach		if ($this->email !== $email) {
453a25f0a04SGreg Roach			$this->email = $email;
454a25f0a04SGreg Roach			Database::prepare(
455a25f0a04SGreg Roach				"UPDATE `##user` SET email = ? WHERE user_id = ?"
45613abd6f3SGreg Roach			)->execute([$email, $this->user_id]);
457a25f0a04SGreg Roach		}
458a25f0a04SGreg Roach
459a25f0a04SGreg Roach		return $this;
460a25f0a04SGreg Roach	}
461a25f0a04SGreg Roach
462a25f0a04SGreg Roach	/**
463a25f0a04SGreg Roach	 * Set the password of this user.
464a25f0a04SGreg Roach	 *
465a25f0a04SGreg Roach	 * @param string $password
466a25f0a04SGreg Roach	 *
467a25f0a04SGreg Roach	 * @return User
468a25f0a04SGreg Roach	 */
469a25f0a04SGreg Roach	public function setPassword($password) {
470a25f0a04SGreg Roach		Database::prepare(
471015c99a2SGreg Roach			"UPDATE `##user` SET password = :password WHERE user_id = :user_id"
472015c99a2SGreg Roach		)->execute([
473015c99a2SGreg Roach			'password' => password_hash($password, PASSWORD_DEFAULT),
474015c99a2SGreg Roach			'user_id'  => $this->user_id,
475015c99a2SGreg Roach		]);
476a25f0a04SGreg Roach
477a25f0a04SGreg Roach		return $this;
478a25f0a04SGreg Roach	}
479a25f0a04SGreg Roach
480a25f0a04SGreg Roach	/**
481a25f0a04SGreg Roach	 * Fetch a user option/setting from the wt_user_setting table.
482a25f0a04SGreg Roach	 *
483a25f0a04SGreg Roach	 * Since we'll fetch several settings for each user, and since there aren’t
484a25f0a04SGreg Roach	 * that many of them, fetch them all in one database query
485a25f0a04SGreg Roach	 *
486a25f0a04SGreg Roach	 * @param string $setting_name
48715d603e7SGreg Roach	 * @param string $default
488a25f0a04SGreg Roach	 *
48915d603e7SGreg Roach	 * @return string
490a25f0a04SGreg Roach	 */
49115d603e7SGreg Roach	public function getPreference($setting_name, $default = '') {
492*c04dd3c1SGreg Roach		if (empty($this->preferences) && $this->user_id !== 0) {
493a25f0a04SGreg Roach			$this->preferences = Database::prepare(
49415d603e7SGreg Roach				"SELECT SQL_CACHE setting_name, setting_value" .
49515d603e7SGreg Roach				" FROM `##user_setting`" .
49615d603e7SGreg Roach				" WHERE user_id = :user_id"
49715d603e7SGreg Roach			)->execute([
49815d603e7SGreg Roach				'user_id' => $this->user_id,
49915d603e7SGreg Roach			])->fetchAssoc();
500a25f0a04SGreg Roach		}
501a25f0a04SGreg Roach
50215d603e7SGreg Roach		if (!array_key_exists($setting_name, $this->preferences)) {
50315d603e7SGreg Roach			$this->preferences[$setting_name] = $default;
504a25f0a04SGreg Roach		}
50515d603e7SGreg Roach
50615d603e7SGreg Roach		return $this->preferences[$setting_name];
507a25f0a04SGreg Roach	}
508a25f0a04SGreg Roach
509a25f0a04SGreg Roach	/**
510a25f0a04SGreg Roach	 * Update a setting for the user.
511a25f0a04SGreg Roach	 *
512a25f0a04SGreg Roach	 * @param string $setting_name
513a25f0a04SGreg Roach	 * @param string $setting_value
514a25f0a04SGreg Roach	 *
515a25f0a04SGreg Roach	 * @return User
516a25f0a04SGreg Roach	 */
517a25f0a04SGreg Roach	public function setPreference($setting_name, $setting_value) {
518*c04dd3c1SGreg Roach		if ($this->user_id !== 0 && $this->getPreference($setting_name) !== $setting_value) {
519a25f0a04SGreg Roach			Database::prepare("REPLACE INTO `##user_setting` (user_id, setting_name, setting_value) VALUES (?, ?, LEFT(?, 255))")
52013abd6f3SGreg Roach				->execute([$this->user_id, $setting_name, $setting_value]);
52115d603e7SGreg Roach
522a25f0a04SGreg Roach			$this->preferences[$setting_name] = $setting_value;
523a25f0a04SGreg Roach		}
524a25f0a04SGreg Roach
525a25f0a04SGreg Roach		return $this;
526a25f0a04SGreg Roach	}
527a25f0a04SGreg Roach}
528