xref: /webtrees/app/User.php (revision 895230eed7521b5cd885b90d4f5310405ff0b69a)
1a25f0a04SGreg Roach<?php
2a25f0a04SGreg Roach/**
3a25f0a04SGreg Roach * webtrees: online genealogy
48fcd0d32SGreg Roach * Copyright (C) 2019 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 */
16c04dd3c1SGreg Roachdeclare(strict_types=1);
17c04dd3c1SGreg Roach
1876692c8bSGreg Roachnamespace Fisharebest\Webtrees;
19a25f0a04SGreg Roach
208b67c11aSGreg Roachuse Closure;
2101461f86SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
2201461f86SGreg Roachuse Illuminate\Database\Query\Builder;
23639e2984SGreg Roachuse Illuminate\Database\Query\JoinClause;
248b67c11aSGreg Roachuse Illuminate\Support\Collection;
25b0b72ea4SGreg Roachuse stdClass;
2660bc3e3fSGreg Roach
27a25f0a04SGreg Roach/**
2876692c8bSGreg Roach * Provide an interface to the wt_user table.
29a25f0a04SGreg Roach */
30c1010edaSGreg Roachclass User
31c1010edaSGreg Roach{
32c04dd3c1SGreg Roach    /** @var  int The primary key of this user. */
33a25f0a04SGreg Roach    private $user_id;
34a25f0a04SGreg Roach
35a25f0a04SGreg Roach    /** @var  string The login name of this user. */
36a25f0a04SGreg Roach    private $user_name;
37a25f0a04SGreg Roach
38a25f0a04SGreg Roach    /** @var  string The real (display) name of this user. */
39a25f0a04SGreg Roach    private $real_name;
40a25f0a04SGreg Roach
41a25f0a04SGreg Roach    /** @var  string The email address of this user. */
42a25f0a04SGreg Roach    private $email;
43a25f0a04SGreg Roach
4415d603e7SGreg Roach    /** @var string[] Cached copy of the wt_user_setting table. */
4515d603e7SGreg Roach    private $preferences = [];
46a25f0a04SGreg Roach
47a25f0a04SGreg Roach    /**
48f7fb7d41SGreg Roach     * Create a new user object from a row in the database.
49f7fb7d41SGreg Roach     *
508b67c11aSGreg Roach     * @param int    $user_id
518b67c11aSGreg Roach     * @param string $user_name
528b67c11aSGreg Roach     * @param string $real_name
538b67c11aSGreg Roach     * @param string $email
54f7fb7d41SGreg Roach     */
558b67c11aSGreg Roach    private function __construct(int $user_id, string $user_name, string $real_name, string $email)
56c1010edaSGreg Roach    {
578b67c11aSGreg Roach        $this->user_id   = $user_id;
588b67c11aSGreg Roach        $this->user_name = $user_name;
598b67c11aSGreg Roach        $this->real_name = $real_name;
608b67c11aSGreg Roach        $this->email     = $email;
618b67c11aSGreg Roach    }
628b67c11aSGreg Roach
638b67c11aSGreg Roach    /**
648b67c11aSGreg Roach     * A closure which will create an object from a database row.
658b67c11aSGreg Roach     *
668b67c11aSGreg Roach     * @return Closure
678b67c11aSGreg Roach     */
688b67c11aSGreg Roach    public static function rowMapper(): Closure
698b67c11aSGreg Roach    {
708b67c11aSGreg Roach        return function (stdClass $row): User {
718b67c11aSGreg Roach            return new static((int) $row->user_id, $row->user_name, $row->real_name, $row->email);
728b67c11aSGreg Roach        };
738b67c11aSGreg Roach    }
748b67c11aSGreg Roach
758b67c11aSGreg Roach    /**
768b67c11aSGreg Roach     * Create a dummy user from a tree, to send messages.
778b67c11aSGreg Roach     *
788b67c11aSGreg Roach     * @param Tree $tree
798b67c11aSGreg Roach     *
808b67c11aSGreg Roach     * @return User
818b67c11aSGreg Roach     */
825cdfbae8SGreg Roach    public static function userFromTree(Tree $tree): User
835cdfbae8SGreg Roach    {
848b67c11aSGreg Roach        return  new static(0, '', $tree->title(),$tree->getPreference('WEBTREES_EMAIL'));
858b67c11aSGreg Roach    }
868b67c11aSGreg Roach
878b67c11aSGreg Roach    /**
888b67c11aSGreg Roach     * A dummy/null user for visitors.
898b67c11aSGreg Roach     *
908b67c11aSGreg Roach     * @param string $real_name
918b67c11aSGreg Roach     * @param string $email
928b67c11aSGreg Roach     *
938b67c11aSGreg Roach     * @return User
948b67c11aSGreg Roach     */
958b67c11aSGreg Roach    public static function visitor(string $real_name = '', string $email = ''): User
968b67c11aSGreg Roach    {
978b67c11aSGreg Roach        return new static(0, '', $real_name, $email);
98f7fb7d41SGreg Roach    }
99f7fb7d41SGreg Roach
100f7fb7d41SGreg Roach    /**
101f7fb7d41SGreg Roach     * Create a new user.
102f7fb7d41SGreg Roach     * The calling code needs to check for duplicates identifiers before calling
103f7fb7d41SGreg Roach     * this function.
104f7fb7d41SGreg Roach     *
105f7fb7d41SGreg Roach     * @param string $user_name
106f7fb7d41SGreg Roach     * @param string $real_name
107f7fb7d41SGreg Roach     * @param string $email
108f7fb7d41SGreg Roach     * @param string $password
109f7fb7d41SGreg Roach     *
110f7fb7d41SGreg Roach     * @return User
111f7fb7d41SGreg Roach     */
1128f53f488SRico Sonntag    public static function create($user_name, $real_name, $email, $password): User
113c1010edaSGreg Roach    {
11401461f86SGreg Roach        DB::table('user')->insert([
115f7fb7d41SGreg Roach            'user_name' => $user_name,
116f7fb7d41SGreg Roach            'real_name' => $real_name,
117f7fb7d41SGreg Roach            'email'     => $email,
118f7fb7d41SGreg Roach            'password'  => password_hash($password, PASSWORD_DEFAULT),
119f7fb7d41SGreg Roach        ]);
120f7fb7d41SGreg Roach
121f7fb7d41SGreg Roach        // Set default blocks for this user
122f7fb7d41SGreg Roach        $user = self::findByIdentifier($user_name);
12301461f86SGreg Roach
12401461f86SGreg Roach        (new Builder(DB::connection()))->from('block')->insertUsing(
12501461f86SGreg Roach            ['user_id', 'location', 'block_order', 'module_name'],
12601461f86SGreg Roach            function (Builder $query) use ($user): void {
12701461f86SGreg Roach                $query
128*895230eeSGreg Roach                    ->select([DB::raw($user->id()), 'location', 'block_order', 'module_name'])
12901461f86SGreg Roach                    ->from('block')
13001461f86SGreg Roach                    ->where('user_id', '=', -1);
13101461f86SGreg Roach            }
13201461f86SGreg Roach        );
133f7fb7d41SGreg Roach
134f7fb7d41SGreg Roach        return $user;
135f7fb7d41SGreg Roach    }
136f7fb7d41SGreg Roach
137f7fb7d41SGreg Roach    /**
138f7fb7d41SGreg Roach     * Delete a user
139fa4036e8SGreg Roach     *
140fa4036e8SGreg Roach     * @return void
141f7fb7d41SGreg Roach     */
142c1010edaSGreg Roach    public function delete()
143c1010edaSGreg Roach    {
14437b0f34fSGreg Roach        // Don't delete the logs, just set the user to null.
14537b0f34fSGreg Roach        DB::table('log')
14637b0f34fSGreg Roach            ->where('user_id', '=', $this->user_id)
14737b0f34fSGreg Roach            ->update(['user_id' => null]);
14837b0f34fSGreg Roach
149f7fb7d41SGreg Roach        // Take over the user’s pending changes. (What else could we do with them?)
15037b0f34fSGreg Roach        DB::table('change')
15137b0f34fSGreg Roach            ->where('user_id', '=', $this->user_id)
15237b0f34fSGreg Roach            ->where('status', '=', 'rejected')
15337b0f34fSGreg Roach            ->delete();
15437b0f34fSGreg Roach
15537b0f34fSGreg Roach        DB::table('change')
15637b0f34fSGreg Roach            ->where('user_id', '=', $this->user_id)
15737b0f34fSGreg Roach            ->update(['user_id' => Auth::id()]);
15837b0f34fSGreg Roach
15937b0f34fSGreg Roach        // Take over the user's contact details
16037b0f34fSGreg Roach        DB::table('gedcom_setting')
16137b0f34fSGreg Roach            ->where('setting_value', '=', $this->user_id)
16237b0f34fSGreg Roach            ->whereIn('setting_name', ['CONTACT_USER_ID', 'WEBMASTER_USER_ID'])
16337b0f34fSGreg Roach            ->update(['setting_value' => Auth::id()]);
16437b0f34fSGreg Roach
16537b0f34fSGreg Roach        // Delete settings and preferences
16637b0f34fSGreg Roach        DB::table('block_setting')
16737b0f34fSGreg Roach            ->join('block', 'block_setting.block_id', '=', 'block.block_id')
16837b0f34fSGreg Roach            ->where('user_id', '=', $this->user_id)
16937b0f34fSGreg Roach            ->delete();
17037b0f34fSGreg Roach
17137b0f34fSGreg Roach        DB::table('block')->where('user_id', '=', $this->user_id)->delete();
17237b0f34fSGreg Roach        DB::table('user_gedcom_setting')->where('user_id', '=', $this->user_id)->delete();
17337b0f34fSGreg Roach        DB::table('user_setting')->where('user_id', '=', $this->user_id)->delete();
17437b0f34fSGreg Roach        DB::table('message')->where('user_id', '=', $this->user_id)->delete();
17537b0f34fSGreg Roach        DB::table('user')->where('user_id', '=', $this->user_id)->delete();
176f7fb7d41SGreg Roach    }
177f7fb7d41SGreg Roach
178f7fb7d41SGreg Roach    /**
179a25f0a04SGreg Roach     * Find the user with a specified user_id.
180a25f0a04SGreg Roach     *
181cbc1590aSGreg Roach     * @param int|null $user_id
182a25f0a04SGreg Roach     *
183a25f0a04SGreg Roach     * @return User|null
184a25f0a04SGreg Roach     */
185c1010edaSGreg Roach    public static function find($user_id)
186c1010edaSGreg Roach    {
1878b67c11aSGreg Roach        return app('cache.array')->rememberForever(__CLASS__ . $user_id, function () use ($user_id) {
1888b67c11aSGreg Roach            return DB::table('user')
18901461f86SGreg Roach                ->where('user_id', '=', $user_id)
1908b67c11aSGreg Roach                ->get();
1918b67c11aSGreg Roach        })
1928b67c11aSGreg Roach        ->map(static::rowMapper())
19301461f86SGreg Roach        ->first();
194a25f0a04SGreg Roach    }
195a25f0a04SGreg Roach
196a25f0a04SGreg Roach    /**
197a982a56eSGreg Roach     * Find the user with a specified email address.
198a982a56eSGreg Roach     *
199a982a56eSGreg Roach     * @param string $email
200a982a56eSGreg Roach     *
201a982a56eSGreg Roach     * @return User|null
202a982a56eSGreg Roach     */
203c1010edaSGreg Roach    public static function findByEmail($email)
204c1010edaSGreg Roach    {
2058b67c11aSGreg Roach        return DB::table('user')
20601461f86SGreg Roach            ->where('email', '=', $email)
2078b67c11aSGreg Roach            ->get()
2088b67c11aSGreg Roach            ->map(static::rowMapper())
2098b67c11aSGreg Roach            ->first();
210a982a56eSGreg Roach    }
211a982a56eSGreg Roach
212a982a56eSGreg Roach    /**
213a982a56eSGreg Roach     * Find the user with a specified user_name or email address.
214a25f0a04SGreg Roach     *
215a25f0a04SGreg Roach     * @param string $identifier
216a25f0a04SGreg Roach     *
217a25f0a04SGreg Roach     * @return User|null
218a25f0a04SGreg Roach     */
219c1010edaSGreg Roach    public static function findByIdentifier($identifier)
220c1010edaSGreg Roach    {
2218b67c11aSGreg Roach        return DB::table('user')
22201461f86SGreg Roach            ->where('user_name', '=', $identifier)
22301461f86SGreg Roach            ->orWhere('email', '=', $identifier)
2248b67c11aSGreg Roach            ->get()
2258b67c11aSGreg Roach            ->map(static::rowMapper())
2268b67c11aSGreg Roach            ->first();
227a25f0a04SGreg Roach    }
228a25f0a04SGreg Roach
229a25f0a04SGreg Roach    /**
230bc09afc5SGreg Roach     * Find the user(s) with a specified genealogy record.
231a25f0a04SGreg Roach     *
232a25f0a04SGreg Roach     * @param Individual $individual
233a25f0a04SGreg Roach     *
2348b67c11aSGreg Roach     * @return Collection|User[]
235a25f0a04SGreg Roach     */
2368b67c11aSGreg Roach    public static function findByIndividual(Individual $individual): Collection
237c1010edaSGreg Roach    {
2388b67c11aSGreg Roach        return DB::table('user')
2398b67c11aSGreg Roach            ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id')
240bc09afc5SGreg Roach            ->where('gedcom_id', '=', $individual->tree()->id())
241bc09afc5SGreg Roach            ->where('setting_value', '=', $individual->xref())
242bc09afc5SGreg Roach            ->where('setting_name', '=', 'gedcomid')
2438b67c11aSGreg Roach            ->select(['user.*'])
2448b67c11aSGreg Roach            ->get()
2458b67c11aSGreg Roach            ->map(static::rowMapper());
246a25f0a04SGreg Roach    }
247a25f0a04SGreg Roach
248a25f0a04SGreg Roach    /**
249f7fb7d41SGreg Roach     * Find the user with a specified user_name.
250f7fb7d41SGreg Roach     *
251f7fb7d41SGreg Roach     * @param string $user_name
252f7fb7d41SGreg Roach     *
253f7fb7d41SGreg Roach     * @return User|null
254f7fb7d41SGreg Roach     */
255c1010edaSGreg Roach    public static function findByUserName($user_name)
256c1010edaSGreg Roach    {
2578b67c11aSGreg Roach        return DB::table('user')
25801461f86SGreg Roach            ->where('user_name', '=', $user_name)
2598b67c11aSGreg Roach            ->get()
2608b67c11aSGreg Roach            ->map(static::rowMapper())
2618b67c11aSGreg Roach            ->first();
262f7fb7d41SGreg Roach    }
263f7fb7d41SGreg Roach
264f7fb7d41SGreg Roach    /**
265a25f0a04SGreg Roach     * Get a list of all users.
266a25f0a04SGreg Roach     *
2678b67c11aSGreg Roach     * @return Collection|User[]
268a25f0a04SGreg Roach     */
2698b67c11aSGreg Roach    public static function all(): Collection
270c1010edaSGreg Roach    {
2718b67c11aSGreg Roach        return DB::table('user')
272639e2984SGreg Roach            ->where('user_id', '>', 0)
273639e2984SGreg Roach            ->orderBy('real_name')
274639e2984SGreg Roach            ->select(['user_id', 'user_name', 'real_name', 'email'])
2758b67c11aSGreg Roach            ->get()
2768b67c11aSGreg Roach            ->map(static::rowMapper());
277a25f0a04SGreg Roach    }
278a25f0a04SGreg Roach
279a25f0a04SGreg Roach    /**
280a25f0a04SGreg Roach     * Get a list of all administrators.
281a25f0a04SGreg Roach     *
2828b67c11aSGreg Roach     * @return Collection|User[]
283a25f0a04SGreg Roach     */
2848b67c11aSGreg Roach    public static function administrators(): Collection
285c1010edaSGreg Roach    {
2868b67c11aSGreg Roach        return DB::table('user')
287639e2984SGreg Roach            ->join('user_setting', function (JoinClause $join): void {
288639e2984SGreg Roach                $join
289639e2984SGreg Roach                    ->on('user_setting.user_id', '=', 'user.user_id')
290639e2984SGreg Roach                    ->where('user_setting.setting_name', '=', 'canadmin')
291639e2984SGreg Roach                    ->where('user_setting.setting_value', '=', '1');
292639e2984SGreg Roach            })
293639e2984SGreg Roach            ->where('user.user_id', '>', 0)
294639e2984SGreg Roach            ->orderBy('real_name')
295639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
2968b67c11aSGreg Roach            ->get()
2978b67c11aSGreg Roach            ->map(static::rowMapper());
298a25f0a04SGreg Roach    }
299a25f0a04SGreg Roach
300fa4036e8SGreg Roach    /**
301fa4036e8SGreg Roach     * Validate a supplied password
302c1010edaSGreg Roach     *
303a25f0a04SGreg Roach     * @param string $password
304a25f0a04SGreg Roach     *
305cbc1590aSGreg Roach     * @return bool
306a25f0a04SGreg Roach     */
307fa4036e8SGreg Roach    public function checkPassword(string $password): bool
308c1010edaSGreg Roach    {
309639e2984SGreg Roach        $password_hash = DB::table('user')
310639e2984SGreg Roach            ->where('user_id', '=', $this->user_id)
311639e2984SGreg Roach            ->value('password');
312a25f0a04SGreg Roach
313bbd8bd1bSGreg Roach        if ($password_hash !== null && password_verify($password, $password_hash)) {
314015c99a2SGreg Roach            if (password_needs_rehash($password_hash, PASSWORD_DEFAULT)) {
315a25f0a04SGreg Roach                $this->setPassword($password);
316a25f0a04SGreg Roach            }
317cbc1590aSGreg Roach
318a25f0a04SGreg Roach            return true;
319a25f0a04SGreg Roach        }
320b2ce94c6SRico Sonntag
321b2ce94c6SRico Sonntag        return false;
322a25f0a04SGreg Roach    }
323a25f0a04SGreg Roach
324a25f0a04SGreg Roach    /**
325f7fb7d41SGreg Roach     * Get a list of all managers.
326f7fb7d41SGreg Roach     *
3278b67c11aSGreg Roach     * @return Collection|User[]
328f7fb7d41SGreg Roach     */
3298b67c11aSGreg Roach    public static function managers(): Collection
330c1010edaSGreg Roach    {
3318b67c11aSGreg Roach        return DB::table('user')
332639e2984SGreg Roach            ->join('user_gedcom_setting', function (JoinClause $join): void {
333639e2984SGreg Roach                $join
334639e2984SGreg Roach                    ->on('user_gedcom_setting.user_id', '=', 'user.user_id')
335639e2984SGreg Roach                    ->where('user_gedcom_setting.setting_name', '=', 'canedit')
336639e2984SGreg Roach                    ->where('user_gedcom_setting.setting_value', '=', 'admin');
337639e2984SGreg Roach            })
338639e2984SGreg Roach            ->where('user.user_id', '>', 0)
339639e2984SGreg Roach            ->orderBy('real_name')
340639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
3418b67c11aSGreg Roach            ->get()
3428b67c11aSGreg Roach            ->map(static::rowMapper());
343f7fb7d41SGreg Roach    }
344f7fb7d41SGreg Roach
345f7fb7d41SGreg Roach    /**
346f7fb7d41SGreg Roach     * Get a list of all moderators.
347f7fb7d41SGreg Roach     *
3488b67c11aSGreg Roach     * @return Collection|User[]
349f7fb7d41SGreg Roach     */
3508b67c11aSGreg Roach    public static function moderators(): Collection
351c1010edaSGreg Roach    {
3528b67c11aSGreg Roach        return DB::table('user')
353639e2984SGreg Roach            ->join('user_gedcom_setting', function (JoinClause $join): void {
354639e2984SGreg Roach                $join
355639e2984SGreg Roach                    ->on('user_gedcom_setting.user_id', '=', 'user.user_id')
356639e2984SGreg Roach                    ->where('user_gedcom_setting.setting_name', '=', 'canedit')
357639e2984SGreg Roach                    ->where('user_gedcom_setting.setting_value', '=', 'accept');
358639e2984SGreg Roach            })
359639e2984SGreg Roach            ->where('user.user_id', '>', 0)
360639e2984SGreg Roach            ->orderBy('real_name')
361639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
3628b67c11aSGreg Roach            ->get()
3638b67c11aSGreg Roach            ->map(static::rowMapper());
364f7fb7d41SGreg Roach    }
365f7fb7d41SGreg Roach
366f7fb7d41SGreg Roach    /**
367f7fb7d41SGreg Roach     * Get a list of all verified users.
368f7fb7d41SGreg Roach     *
3698b67c11aSGreg Roach     * @return Collection|User[]
370f7fb7d41SGreg Roach     */
3718b67c11aSGreg Roach    public static function unapproved(): Collection
372c1010edaSGreg Roach    {
3738b67c11aSGreg Roach        return DB::table('user')
374639e2984SGreg Roach            ->join('user_setting', function (JoinClause $join): void {
375639e2984SGreg Roach                $join
376639e2984SGreg Roach                    ->on('user_setting.user_id', '=', 'user.user_id')
377639e2984SGreg Roach                    ->where('user_setting.setting_name', '=', 'verified_by_admin')
378639e2984SGreg Roach                    ->where('user_setting.setting_value', '=', '0');
379639e2984SGreg Roach            })
380639e2984SGreg Roach            ->where('user.user_id', '>', 0)
381639e2984SGreg Roach            ->orderBy('real_name')
382639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
3838b67c11aSGreg Roach            ->get()
3848b67c11aSGreg Roach            ->map(static::rowMapper());
385f7fb7d41SGreg Roach    }
386f7fb7d41SGreg Roach
387f7fb7d41SGreg Roach    /**
388f7fb7d41SGreg Roach     * Get a list of all verified users.
389f7fb7d41SGreg Roach     *
3908b67c11aSGreg Roach     * @return Collection|User[]
391f7fb7d41SGreg Roach     */
3928b67c11aSGreg Roach    public static function unverified(): Collection
393c1010edaSGreg Roach    {
3948b67c11aSGreg Roach        return DB::table('user')
395639e2984SGreg Roach            ->join('user_setting', function (JoinClause $join): void {
396639e2984SGreg Roach                $join
397639e2984SGreg Roach                    ->on('user_setting.user_id', '=', 'user.user_id')
398639e2984SGreg Roach                    ->where('user_setting.setting_name', '=', 'verified')
399639e2984SGreg Roach                    ->where('user_setting.setting_value', '=', '0');
400639e2984SGreg Roach            })
401639e2984SGreg Roach            ->where('user.user_id', '>', 0)
402639e2984SGreg Roach            ->orderBy('real_name')
403639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
4048b67c11aSGreg Roach            ->get()
4058b67c11aSGreg Roach            ->map(static::rowMapper());
406f7fb7d41SGreg Roach    }
407f7fb7d41SGreg Roach
408f7fb7d41SGreg Roach    /**
409f7fb7d41SGreg Roach     * Get a list of all users who are currently logged in.
410f7fb7d41SGreg Roach     *
4118b67c11aSGreg Roach     * @return Collection|User[]
412f7fb7d41SGreg Roach     */
4138b67c11aSGreg Roach    public static function allLoggedIn(): Collection
414c1010edaSGreg Roach    {
4158b67c11aSGreg Roach        return DB::table('user')
416639e2984SGreg Roach            ->join('session', 'session.user_id', '=', 'user.user_id')
417639e2984SGreg Roach            ->where('user.user_id', '>', 0)
418639e2984SGreg Roach            ->orderBy('real_name')
419639e2984SGreg Roach            ->select(['user.user_id', 'user_name', 'real_name', 'email'])
420639e2984SGreg Roach            ->distinct()
4218b67c11aSGreg Roach            ->get()
4228b67c11aSGreg Roach            ->map(static::rowMapper());
423f7fb7d41SGreg Roach    }
424f7fb7d41SGreg Roach
425f7fb7d41SGreg Roach    /**
426a25f0a04SGreg Roach     * Get the numeric ID for this user.
427a25f0a04SGreg Roach     *
428c04dd3c1SGreg Roach     * @return int
429a25f0a04SGreg Roach     */
430*895230eeSGreg Roach    public function id(): int
431c1010edaSGreg Roach    {
432a25f0a04SGreg Roach        return $this->user_id;
433a25f0a04SGreg Roach    }
434a25f0a04SGreg Roach
435a25f0a04SGreg Roach    /**
436a25f0a04SGreg Roach     * Get the login name for this user.
437a25f0a04SGreg Roach     *
438a25f0a04SGreg Roach     * @return string
439a25f0a04SGreg Roach     */
4408f53f488SRico Sonntag    public function getUserName(): string
441c1010edaSGreg Roach    {
442a25f0a04SGreg Roach        return $this->user_name;
443a25f0a04SGreg Roach    }
444a25f0a04SGreg Roach
445a25f0a04SGreg Roach    /**
446a25f0a04SGreg Roach     * Set the login name for this user.
447a25f0a04SGreg Roach     *
448a25f0a04SGreg Roach     * @param string $user_name
449a25f0a04SGreg Roach     *
450a25f0a04SGreg Roach     * @return $this
451a25f0a04SGreg Roach     */
4528f53f488SRico Sonntag    public function setUserName($user_name): self
453c1010edaSGreg Roach    {
454a25f0a04SGreg Roach        if ($this->user_name !== $user_name) {
455a25f0a04SGreg Roach            $this->user_name = $user_name;
45601461f86SGreg Roach
45701461f86SGreg Roach            DB::table('user')
45801461f86SGreg Roach                ->where('user_id', '=', $this->user_id)
45901461f86SGreg Roach                ->update([
46001461f86SGreg Roach                    'user_name' => $user_name,
461c1010edaSGreg Roach                ]);
462a25f0a04SGreg Roach        }
463a25f0a04SGreg Roach
464a25f0a04SGreg Roach        return $this;
465a25f0a04SGreg Roach    }
466a25f0a04SGreg Roach
467a25f0a04SGreg Roach    /**
468a25f0a04SGreg Roach     * Get the real name of this user.
469a25f0a04SGreg Roach     *
470a25f0a04SGreg Roach     * @return string
471a25f0a04SGreg Roach     */
4728f53f488SRico Sonntag    public function getRealName(): string
473c1010edaSGreg Roach    {
474a25f0a04SGreg Roach        return $this->real_name;
475a25f0a04SGreg Roach    }
476a25f0a04SGreg Roach
477a25f0a04SGreg Roach    /**
478a25f0a04SGreg Roach     * Set the real name of this user.
479a25f0a04SGreg Roach     *
480a25f0a04SGreg Roach     * @param string $real_name
481a25f0a04SGreg Roach     *
482a25f0a04SGreg Roach     * @return User
483a25f0a04SGreg Roach     */
4848f53f488SRico Sonntag    public function setRealName($real_name): User
485c1010edaSGreg Roach    {
486a25f0a04SGreg Roach        if ($this->real_name !== $real_name) {
487a25f0a04SGreg Roach            $this->real_name = $real_name;
48801461f86SGreg Roach
48901461f86SGreg Roach            DB::table('user')
49001461f86SGreg Roach                ->where('user_id', '=', $this->user_id)
49101461f86SGreg Roach                ->update([
49201461f86SGreg Roach                    'real_name' => $real_name,
493c1010edaSGreg Roach                ]);
494a25f0a04SGreg Roach        }
495a25f0a04SGreg Roach
496a25f0a04SGreg Roach        return $this;
497a25f0a04SGreg Roach    }
498a25f0a04SGreg Roach
499a25f0a04SGreg Roach    /**
500a25f0a04SGreg Roach     * Get the email address of this user.
501a25f0a04SGreg Roach     *
502a25f0a04SGreg Roach     * @return string
503a25f0a04SGreg Roach     */
5048f53f488SRico Sonntag    public function getEmail(): string
505c1010edaSGreg Roach    {
506a25f0a04SGreg Roach        return $this->email;
507a25f0a04SGreg Roach    }
508a25f0a04SGreg Roach
509a25f0a04SGreg Roach    /**
510a25f0a04SGreg Roach     * Set the email address of this user.
511a25f0a04SGreg Roach     *
512a25f0a04SGreg Roach     * @param string $email
513a25f0a04SGreg Roach     *
514a25f0a04SGreg Roach     * @return User
515a25f0a04SGreg Roach     */
5168f53f488SRico Sonntag    public function setEmail($email): User
517c1010edaSGreg Roach    {
518a25f0a04SGreg Roach        if ($this->email !== $email) {
519a25f0a04SGreg Roach            $this->email = $email;
52001461f86SGreg Roach
52101461f86SGreg Roach            DB::table('user')
52201461f86SGreg Roach                ->where('user_id', '=', $this->user_id)
52301461f86SGreg Roach                ->update([
52401461f86SGreg Roach                    'email' => $email,
525c1010edaSGreg Roach                ]);
526a25f0a04SGreg Roach        }
527a25f0a04SGreg Roach
528a25f0a04SGreg Roach        return $this;
529a25f0a04SGreg Roach    }
530a25f0a04SGreg Roach
531a25f0a04SGreg Roach    /**
532a25f0a04SGreg Roach     * Set the password of this user.
533a25f0a04SGreg Roach     *
534a25f0a04SGreg Roach     * @param string $password
535a25f0a04SGreg Roach     *
536a25f0a04SGreg Roach     * @return User
537a25f0a04SGreg Roach     */
5388f53f488SRico Sonntag    public function setPassword($password): User
539c1010edaSGreg Roach    {
54001461f86SGreg Roach        DB::table('user')
54101461f86SGreg Roach            ->where('user_id', '=', $this->user_id)
54201461f86SGreg Roach            ->update([
543015c99a2SGreg Roach                'password' => password_hash($password, PASSWORD_DEFAULT),
544015c99a2SGreg Roach            ]);
545a25f0a04SGreg Roach
546a25f0a04SGreg Roach        return $this;
547a25f0a04SGreg Roach    }
548a25f0a04SGreg Roach
549a25f0a04SGreg Roach    /**
550a25f0a04SGreg Roach     * Fetch a user option/setting from the wt_user_setting table.
551a25f0a04SGreg Roach     * Since we'll fetch several settings for each user, and since there aren’t
552a25f0a04SGreg Roach     * that many of them, fetch them all in one database query
553a25f0a04SGreg Roach     *
554a25f0a04SGreg Roach     * @param string $setting_name
55515d603e7SGreg Roach     * @param string $default
556a25f0a04SGreg Roach     *
55715d603e7SGreg Roach     * @return string
558a25f0a04SGreg Roach     */
5598f53f488SRico Sonntag    public function getPreference($setting_name, $default = ''): string
560c1010edaSGreg Roach    {
56183c7613eSGreg Roach        $preferences = app('cache.array')->rememberForever('user_setting' . $this->user_id, function () {
56283c7613eSGreg Roach            if ($this->user_id) {
56383c7613eSGreg Roach                return DB::table('user_setting')
56401461f86SGreg Roach                    ->where('user_id', '=', $this->user_id)
56501461f86SGreg Roach                    ->pluck('setting_value', 'setting_name')
56601461f86SGreg Roach                    ->all();
56783c7613eSGreg Roach            } else {
56883c7613eSGreg Roach                return [];
569a25f0a04SGreg Roach            }
57083c7613eSGreg Roach        });
571a25f0a04SGreg Roach
57283c7613eSGreg Roach        return $preferences[$setting_name] ?? $default;
573a25f0a04SGreg Roach    }
574a25f0a04SGreg Roach
575a25f0a04SGreg Roach    /**
576a25f0a04SGreg Roach     * Update a setting for the user.
577a25f0a04SGreg Roach     *
578a25f0a04SGreg Roach     * @param string $setting_name
579a25f0a04SGreg Roach     * @param string $setting_value
580a25f0a04SGreg Roach     *
581a25f0a04SGreg Roach     * @return User
582a25f0a04SGreg Roach     */
5838f53f488SRico Sonntag    public function setPreference($setting_name, $setting_value): User
584c1010edaSGreg Roach    {
585c04dd3c1SGreg Roach        if ($this->user_id !== 0 && $this->getPreference($setting_name) !== $setting_value) {
58601461f86SGreg Roach            DB::table('user_setting')->updateOrInsert([
58701461f86SGreg Roach                'user_id'      => $this->user_id,
58801461f86SGreg Roach                'setting_name' => $setting_name,
58901461f86SGreg Roach            ], [
59001461f86SGreg Roach                'setting_value' => $setting_value,
591c1010edaSGreg Roach            ]);
59215d603e7SGreg Roach
593a25f0a04SGreg Roach            $this->preferences[$setting_name] = $setting_value;
594a25f0a04SGreg Roach        }
595a25f0a04SGreg Roach
596611d1316SGreg Roach        app('cache.array')->forget('user_setting' . $this->user_id);
597611d1316SGreg Roach
598a25f0a04SGreg Roach        return $this;
599a25f0a04SGreg Roach    }
600a25f0a04SGreg Roach}
601