fisharebest /
webtrees
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * webtrees: online genealogy |
||
| 5 | * Copyright (C) 2025 webtrees development team |
||
| 6 | * This program is free software: you can redistribute it and/or modify |
||
| 7 | * it under the terms of the GNU General Public License as published by |
||
| 8 | * the Free Software Foundation, either version 3 of the License, or |
||
| 9 | * (at your option) any later version. |
||
| 10 | * This program is distributed in the hope that it will be useful, |
||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 13 | * GNU General Public License for more details. |
||
| 14 | * You should have received a copy of the GNU General Public License |
||
| 15 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
||
| 16 | */ |
||
| 17 | |||
| 18 | declare(strict_types=1); |
||
| 19 | |||
| 20 | namespace Fisharebest\Webtrees; |
||
| 21 | |||
| 22 | use Closure; |
||
| 23 | use Fisharebest\Webtrees\Contracts\UserInterface; |
||
|
0 ignored issues
–
show
|
|||
| 24 | |||
| 25 | use function is_string; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * Provide an interface to the wt_user table. |
||
| 29 | */ |
||
| 30 | class User implements UserInterface |
||
| 31 | { |
||
| 32 | private int $user_id; |
||
| 33 | |||
| 34 | private string $user_name; |
||
| 35 | |||
| 36 | private string $real_name; |
||
| 37 | |||
| 38 | private string $email; |
||
| 39 | |||
| 40 | /** @var array<string,string> */ |
||
| 41 | private array $preferences; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @param int $user_id |
||
| 45 | * @param string $user_name |
||
| 46 | * @param string $real_name |
||
| 47 | * @param string $email |
||
| 48 | */ |
||
| 49 | public function __construct(int $user_id, string $user_name, string $real_name, string $email) |
||
| 50 | { |
||
| 51 | $this->user_id = $user_id; |
||
| 52 | $this->user_name = $user_name; |
||
| 53 | $this->real_name = $real_name; |
||
| 54 | $this->email = $email; |
||
| 55 | |||
| 56 | $this->preferences = DB::table('user_setting') |
||
| 57 | ->where('user_id', '=', $this->user_id) |
||
| 58 | ->pluck('setting_value', 'setting_name') |
||
| 59 | ->all(); |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * The user‘s internal identifier. |
||
| 64 | * |
||
| 65 | * @return int |
||
| 66 | */ |
||
| 67 | public function id(): int |
||
| 68 | { |
||
| 69 | return $this->user_id; |
||
| 70 | } |
||
| 71 | |||
| 72 | /** |
||
| 73 | * The users email address. |
||
| 74 | * |
||
| 75 | * @return string |
||
| 76 | */ |
||
| 77 | public function email(): string |
||
| 78 | { |
||
| 79 | return $this->email; |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * Set the email address of this user. |
||
| 84 | * |
||
| 85 | * @param string $email |
||
| 86 | * |
||
| 87 | * @return User |
||
| 88 | */ |
||
| 89 | public function setEmail(string $email): User |
||
| 90 | { |
||
| 91 | if ($this->email !== $email) { |
||
| 92 | $this->email = $email; |
||
| 93 | |||
| 94 | DB::table('user') |
||
| 95 | ->where('user_id', '=', $this->user_id) |
||
| 96 | ->update([ |
||
| 97 | 'email' => $email, |
||
| 98 | ]); |
||
| 99 | } |
||
| 100 | |||
| 101 | return $this; |
||
| 102 | } |
||
| 103 | |||
| 104 | /** |
||
| 105 | * The user‘s real name. |
||
| 106 | * |
||
| 107 | * @return string |
||
| 108 | */ |
||
| 109 | public function realName(): string |
||
| 110 | { |
||
| 111 | return $this->real_name; |
||
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Set the real name of this user. |
||
| 116 | * |
||
| 117 | * @param string $real_name |
||
| 118 | * |
||
| 119 | * @return User |
||
| 120 | */ |
||
| 121 | public function setRealName(string $real_name): User |
||
| 122 | { |
||
| 123 | if ($this->real_name !== $real_name) { |
||
| 124 | $this->real_name = $real_name; |
||
| 125 | |||
| 126 | DB::table('user') |
||
| 127 | ->where('user_id', '=', $this->user_id) |
||
| 128 | ->update([ |
||
| 129 | 'real_name' => $real_name, |
||
| 130 | ]); |
||
| 131 | } |
||
| 132 | |||
| 133 | return $this; |
||
| 134 | } |
||
| 135 | |||
| 136 | /** |
||
| 137 | * The user‘s login name. |
||
| 138 | * |
||
| 139 | * @return string |
||
| 140 | */ |
||
| 141 | public function userName(): string |
||
| 142 | { |
||
| 143 | return $this->user_name; |
||
| 144 | } |
||
| 145 | |||
| 146 | /** |
||
| 147 | * Set the login name for this user. |
||
| 148 | * |
||
| 149 | * @param string $user_name |
||
| 150 | * |
||
| 151 | * @return self |
||
| 152 | */ |
||
| 153 | public function setUserName(string $user_name): self |
||
| 154 | { |
||
| 155 | if ($this->user_name !== $user_name) { |
||
| 156 | $this->user_name = $user_name; |
||
| 157 | |||
| 158 | DB::table('user') |
||
| 159 | ->where('user_id', '=', $this->user_id) |
||
| 160 | ->update([ |
||
| 161 | 'user_name' => $user_name, |
||
| 162 | ]); |
||
| 163 | } |
||
| 164 | |||
| 165 | return $this; |
||
| 166 | } |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Fetch a user option/setting from the wt_user_setting table. |
||
| 170 | * Since we'll fetch several settings for each user, and since there aren't |
||
| 171 | * that many of them, fetch them all in one database query |
||
| 172 | * |
||
| 173 | * @param string $setting_name |
||
| 174 | * @param string $default |
||
| 175 | * |
||
| 176 | * @return string |
||
| 177 | */ |
||
| 178 | public function getPreference(string $setting_name, string $default = ''): string |
||
| 179 | { |
||
| 180 | return $this->preferences[$setting_name] ?? $default; |
||
| 181 | } |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Update a setting for the user. |
||
| 185 | * |
||
| 186 | * @param string $setting_name |
||
| 187 | * @param string $setting_value |
||
| 188 | * |
||
| 189 | * @return void |
||
| 190 | */ |
||
| 191 | public function setPreference(string $setting_name, string $setting_value): void |
||
| 192 | { |
||
| 193 | if ($this->getPreference($setting_name) !== $setting_value) { |
||
| 194 | DB::table('user_setting')->updateOrInsert([ |
||
| 195 | 'user_id' => $this->user_id, |
||
| 196 | 'setting_name' => $setting_name, |
||
| 197 | ], [ |
||
| 198 | 'setting_value' => $setting_value, |
||
| 199 | ]); |
||
| 200 | |||
| 201 | $this->preferences[$setting_name] = $setting_value; |
||
| 202 | } |
||
| 203 | } |
||
| 204 | |||
| 205 | /** |
||
| 206 | * Set the password of this user. |
||
| 207 | * |
||
| 208 | * @param string $password |
||
| 209 | * |
||
| 210 | * @return User |
||
| 211 | */ |
||
| 212 | public function setPassword(#[\SensitiveParameter] string $password): User |
||
| 213 | { |
||
| 214 | DB::table('user') |
||
| 215 | ->where('user_id', '=', $this->user_id) |
||
| 216 | ->update([ |
||
| 217 | 'password' => password_hash($password, PASSWORD_DEFAULT), |
||
| 218 | ]); |
||
| 219 | |||
| 220 | return $this; |
||
| 221 | } |
||
| 222 | |||
| 223 | /** |
||
| 224 | * Validate a supplied password |
||
| 225 | * |
||
| 226 | * @param string $password |
||
| 227 | * |
||
| 228 | * @return bool |
||
| 229 | */ |
||
| 230 | public function checkPassword(#[\SensitiveParameter] string $password): bool |
||
| 231 | { |
||
| 232 | $password_hash = DB::table('user') |
||
| 233 | ->where('user_id', '=', $this->id()) |
||
| 234 | ->value('password'); |
||
| 235 | |||
| 236 | if (is_string($password_hash) && password_verify($password, $password_hash)) { |
||
| 237 | if (password_needs_rehash($password_hash, PASSWORD_DEFAULT)) { |
||
| 238 | $this->setPassword($password); |
||
| 239 | } |
||
| 240 | |||
| 241 | return true; |
||
| 242 | } |
||
| 243 | |||
| 244 | return false; |
||
| 245 | } |
||
| 246 | |||
| 247 | /** |
||
| 248 | * A closure which will create an object from a database row. |
||
| 249 | * |
||
| 250 | * @return Closure(object):User |
||
| 251 | */ |
||
| 252 | public static function rowMapper(): Closure |
||
| 253 | { |
||
| 254 | return static fn (object $row): User => new self((int) $row->user_id, $row->user_name, $row->real_name, $row->email); |
||
| 255 | } |
||
| 256 | } |
||
| 257 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths