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