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