xref: /webtrees/app/Services/UserService.php (revision b5c8fd7e66957665381ee23f19cf39bda22bc768)
1e5a6b4d4SGreg Roach<?php
23976b470SGreg Roach
3e5a6b4d4SGreg Roach/**
4e5a6b4d4SGreg Roach * webtrees: online genealogy
5e5a6b4d4SGreg Roach * Copyright (C) 2019 webtrees development team
6e5a6b4d4SGreg Roach * This program is free software: you can redistribute it and/or modify
7e5a6b4d4SGreg Roach * it under the terms of the GNU General Public License as published by
8e5a6b4d4SGreg Roach * the Free Software Foundation, either version 3 of the License, or
9e5a6b4d4SGreg Roach * (at your option) any later version.
10e5a6b4d4SGreg Roach * This program is distributed in the hope that it will be useful,
11e5a6b4d4SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12e5a6b4d4SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13e5a6b4d4SGreg Roach * GNU General Public License for more details.
14e5a6b4d4SGreg Roach * You should have received a copy of the GNU General Public License
15e5a6b4d4SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
16e5a6b4d4SGreg Roach */
17fcfa147eSGreg Roach
18e5a6b4d4SGreg Roachdeclare(strict_types=1);
19e5a6b4d4SGreg Roach
20e5a6b4d4SGreg Roachnamespace Fisharebest\Webtrees\Services;
21e5a6b4d4SGreg Roach
222474349cSGreg Roachuse Closure;
23e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Auth;
24a00bcc63SGreg Roachuse Fisharebest\Webtrees\Carbon;
252474349cSGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
26e381f98dSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\ContactPage;
27e381f98dSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MessagePage;
28e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Individual;
295229eadeSGreg Roachuse Fisharebest\Webtrees\Tree;
30e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\User;
31e5a6b4d4SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
327c4add84SGreg Roachuse Illuminate\Database\Query\Builder;
337c4add84SGreg Roachuse Illuminate\Database\Query\JoinClause;
34e5a6b4d4SGreg Roachuse Illuminate\Support\Collection;
356ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
36f1d4b4a2SGreg Roach
376ccdf4f0SGreg Roachuse function app;
385229eadeSGreg Roachuse function assert;
392474349cSGreg Roachuse function max;
40e5a6b4d4SGreg Roach
41e5a6b4d4SGreg Roach/**
42e5a6b4d4SGreg Roach * Functions for managing users.
43e5a6b4d4SGreg Roach */
44e5a6b4d4SGreg Roachclass UserService
45e5a6b4d4SGreg Roach{
46e5a6b4d4SGreg Roach    /**
47e5a6b4d4SGreg Roach     * Find the user with a specified user_id.
48e5a6b4d4SGreg Roach     *
49e5a6b4d4SGreg Roach     * @param int|null $user_id
50e5a6b4d4SGreg Roach     *
51e5a6b4d4SGreg Roach     * @return User|null
52e5a6b4d4SGreg Roach     */
5325d7fe95SGreg Roach    public function find($user_id): ?User
54e5a6b4d4SGreg Roach    {
557476e8a5SGreg Roach        return app('cache.array')->remember('user-' . $user_id, static function () use ($user_id): ?User {
56e5a6b4d4SGreg Roach            return DB::table('user')
57e5a6b4d4SGreg Roach                ->where('user_id', '=', $user_id)
58e5a6b4d4SGreg Roach                ->get()
59e5a6b4d4SGreg Roach                ->map(User::rowMapper())
60e5a6b4d4SGreg Roach                ->first();
61e5a6b4d4SGreg Roach        });
62e5a6b4d4SGreg Roach    }
63e5a6b4d4SGreg Roach
64e5a6b4d4SGreg Roach    /**
65e5a6b4d4SGreg Roach     * Find the user with a specified email address.
66e5a6b4d4SGreg Roach     *
67e5a6b4d4SGreg Roach     * @param string $email
68e5a6b4d4SGreg Roach     *
69e5a6b4d4SGreg Roach     * @return User|null
70e5a6b4d4SGreg Roach     */
71e364afe4SGreg Roach    public function findByEmail($email): ?User
72e5a6b4d4SGreg Roach    {
73e5a6b4d4SGreg Roach        return DB::table('user')
74e5a6b4d4SGreg Roach            ->where('email', '=', $email)
75e5a6b4d4SGreg Roach            ->get()
76e5a6b4d4SGreg Roach            ->map(User::rowMapper())
77e5a6b4d4SGreg Roach            ->first();
78e5a6b4d4SGreg Roach    }
79e5a6b4d4SGreg Roach
80e5a6b4d4SGreg Roach    /**
81e5a6b4d4SGreg Roach     * Find the user with a specified user_name or email address.
82e5a6b4d4SGreg Roach     *
83e5a6b4d4SGreg Roach     * @param string $identifier
84e5a6b4d4SGreg Roach     *
85e5a6b4d4SGreg Roach     * @return User|null
86e5a6b4d4SGreg Roach     */
87e364afe4SGreg Roach    public function findByIdentifier($identifier): ?User
88e5a6b4d4SGreg Roach    {
89e5a6b4d4SGreg Roach        return DB::table('user')
90e5a6b4d4SGreg Roach            ->where('user_name', '=', $identifier)
91e5a6b4d4SGreg Roach            ->orWhere('email', '=', $identifier)
92e5a6b4d4SGreg Roach            ->get()
93e5a6b4d4SGreg Roach            ->map(User::rowMapper())
94e5a6b4d4SGreg Roach            ->first();
95e5a6b4d4SGreg Roach    }
96e5a6b4d4SGreg Roach
97e5a6b4d4SGreg Roach    /**
98e5a6b4d4SGreg Roach     * Find the user(s) with a specified genealogy record.
99e5a6b4d4SGreg Roach     *
100e5a6b4d4SGreg Roach     * @param Individual $individual
101e5a6b4d4SGreg Roach     *
102*b5c8fd7eSGreg Roach     * @return Collection<User>
103e5a6b4d4SGreg Roach     */
104e5a6b4d4SGreg Roach    public function findByIndividual(Individual $individual): Collection
105e5a6b4d4SGreg Roach    {
106e5a6b4d4SGreg Roach        return DB::table('user')
107e5a6b4d4SGreg Roach            ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id')
108e5a6b4d4SGreg Roach            ->where('gedcom_id', '=', $individual->tree()->id())
109e5a6b4d4SGreg Roach            ->where('setting_value', '=', $individual->xref())
1107c4add84SGreg Roach            ->where('setting_name', '=', User::PREF_TREE_ACCOUNT_XREF)
111e5a6b4d4SGreg Roach            ->select(['user.*'])
112e5a6b4d4SGreg Roach            ->get()
113e5a6b4d4SGreg Roach            ->map(User::rowMapper());
114e5a6b4d4SGreg Roach    }
115e5a6b4d4SGreg Roach
116e5a6b4d4SGreg Roach    /**
117a00bcc63SGreg Roach     * Find the user with a specified password reset token.
118a00bcc63SGreg Roach     *
119a00bcc63SGreg Roach     * @param string $token
120a00bcc63SGreg Roach     *
121a00bcc63SGreg Roach     * @return User|null
122a00bcc63SGreg Roach     */
123a00bcc63SGreg Roach    public function findByToken(string $token): ?User
124a00bcc63SGreg Roach    {
125a00bcc63SGreg Roach        return DB::table('user')
126a00bcc63SGreg Roach            ->join('user_setting AS us1', 'us1.user_id', '=', 'user.user_id')
127a00bcc63SGreg Roach            ->where('us1.setting_name', '=', 'password-token')
128a00bcc63SGreg Roach            ->where('us1.setting_value', '=', $token)
129a00bcc63SGreg Roach            ->join('user_setting AS us2', 'us2.user_id', '=', 'user.user_id')
130a00bcc63SGreg Roach            ->where('us2.setting_name', '=', 'password-token-expire')
131a00bcc63SGreg Roach            ->where('us2.setting_value', '>', Carbon::now()->timestamp)
132a00bcc63SGreg Roach            ->select(['user.*'])
133a00bcc63SGreg Roach            ->get()
134a00bcc63SGreg Roach            ->map(User::rowMapper())
135a00bcc63SGreg Roach            ->first();
136a00bcc63SGreg Roach    }
137a00bcc63SGreg Roach
138a00bcc63SGreg Roach    /**
139e5a6b4d4SGreg Roach     * Find the user with a specified user_name.
140e5a6b4d4SGreg Roach     *
141e5a6b4d4SGreg Roach     * @param string $user_name
142e5a6b4d4SGreg Roach     *
143e5a6b4d4SGreg Roach     * @return User|null
144e5a6b4d4SGreg Roach     */
145e364afe4SGreg Roach    public function findByUserName($user_name): ?User
146e5a6b4d4SGreg Roach    {
147e5a6b4d4SGreg Roach        return DB::table('user')
148e5a6b4d4SGreg Roach            ->where('user_name', '=', $user_name)
149e5a6b4d4SGreg Roach            ->get()
150e5a6b4d4SGreg Roach            ->map(User::rowMapper())
151e5a6b4d4SGreg Roach            ->first();
152e5a6b4d4SGreg Roach    }
153e5a6b4d4SGreg Roach
154e5a6b4d4SGreg Roach    /**
1552474349cSGreg Roach     * Callback to sort users by their last-login (or registration) time.
1562474349cSGreg Roach     *
1572474349cSGreg Roach     * @return Closure
1582474349cSGreg Roach     */
1592474349cSGreg Roach    public function sortByLastLogin(): Closure
1602474349cSGreg Roach    {
1617c4add84SGreg Roach        return static function (UserInterface $user1, UserInterface $user2) {
1627c4add84SGreg Roach            $registered_at1 = (int) $user1->getPreference(User::PREF_TIMESTAMP_REGISTERED);
1637c4add84SGreg Roach            $logged_in_at1  = (int) $user1->getPreference(User::PREF_TIMESTAMP_ACTIVE);
1647c4add84SGreg Roach            $registered_at2 = (int) $user2->getPreference(User::PREF_TIMESTAMP_REGISTERED);
1657c4add84SGreg Roach            $logged_in_at2  = (int) $user2->getPreference(User::PREF_TIMESTAMP_ACTIVE);
1662474349cSGreg Roach
1672474349cSGreg Roach            return max($registered_at1, $logged_in_at1) <=> max($registered_at2, $logged_in_at2);
1682474349cSGreg Roach        };
1692474349cSGreg Roach    }
1702474349cSGreg Roach
1712474349cSGreg Roach    /**
1722474349cSGreg Roach     * Callback to filter users who have not logged in since a given time.
1732474349cSGreg Roach     *
1742474349cSGreg Roach     * @param int $timestamp
1752474349cSGreg Roach     *
1762474349cSGreg Roach     * @return Closure
1772474349cSGreg Roach     */
1782474349cSGreg Roach    public function filterInactive(int $timestamp): Closure
1792474349cSGreg Roach    {
1807c4add84SGreg Roach        return static function (UserInterface $user) use ($timestamp): bool {
1817c4add84SGreg Roach            $registered_at = (int) $user->getPreference(User::PREF_TIMESTAMP_REGISTERED);
1827c4add84SGreg Roach            $logged_in_at  = (int) $user->getPreference(User::PREF_TIMESTAMP_ACTIVE);
1832474349cSGreg Roach
1842474349cSGreg Roach            return max($registered_at, $logged_in_at) < $timestamp;
1852474349cSGreg Roach        };
1862474349cSGreg Roach    }
1872474349cSGreg Roach
1882474349cSGreg Roach    /**
189e5a6b4d4SGreg Roach     * Get a list of all users.
190e5a6b4d4SGreg Roach     *
191*b5c8fd7eSGreg Roach     * @return Collection<User>
192e5a6b4d4SGreg Roach     */
193e5a6b4d4SGreg Roach    public function all(): Collection
194e5a6b4d4SGreg Roach    {
195e5a6b4d4SGreg Roach        return DB::table('user')
196e5a6b4d4SGreg Roach            ->where('user_id', '>', 0)
197e5a6b4d4SGreg Roach            ->orderBy('real_name')
198e5a6b4d4SGreg Roach            ->get()
199e5a6b4d4SGreg Roach            ->map(User::rowMapper());
200e5a6b4d4SGreg Roach    }
201e5a6b4d4SGreg Roach
202e5a6b4d4SGreg Roach    /**
203e5a6b4d4SGreg Roach     * Get a list of all administrators.
204e5a6b4d4SGreg Roach     *
205*b5c8fd7eSGreg Roach     * @return Collection<User>
206e5a6b4d4SGreg Roach     */
207e5a6b4d4SGreg Roach    public function administrators(): Collection
208e5a6b4d4SGreg Roach    {
209e5a6b4d4SGreg Roach        return DB::table('user')
2101ab2f386SGreg Roach            ->join('user_setting', 'user_setting.user_id', '=', 'user.user_id')
2117c4add84SGreg Roach            ->where('user_setting.setting_name', '=', User::PREF_IS_ADMINISTRATOR)
2121ab2f386SGreg Roach            ->where('user_setting.setting_value', '=', '1')
213e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
214e5a6b4d4SGreg Roach            ->orderBy('real_name')
215e5a6b4d4SGreg Roach            ->select(['user.*'])
216e5a6b4d4SGreg Roach            ->get()
217e5a6b4d4SGreg Roach            ->map(User::rowMapper());
218e5a6b4d4SGreg Roach    }
219e5a6b4d4SGreg Roach
220e5a6b4d4SGreg Roach    /**
221e5a6b4d4SGreg Roach     * Get a list of all managers.
222e5a6b4d4SGreg Roach     *
223*b5c8fd7eSGreg Roach     * @return Collection<User>
224e5a6b4d4SGreg Roach     */
225e5a6b4d4SGreg Roach    public function managers(): Collection
226e5a6b4d4SGreg Roach    {
227e5a6b4d4SGreg Roach        return DB::table('user')
2281ab2f386SGreg Roach            ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id')
2297c4add84SGreg Roach            ->where('user_gedcom_setting.setting_name', '=', User::PREF_TREE_ROLE)
2307c4add84SGreg Roach            ->where('user_gedcom_setting.setting_value', '=', User::ROLE_MANAGER)
231e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
2321ab2f386SGreg Roach            ->groupBy(['user.user_id'])
233e5a6b4d4SGreg Roach            ->orderBy('real_name')
234e5a6b4d4SGreg Roach            ->select(['user.*'])
235e5a6b4d4SGreg Roach            ->get()
236e5a6b4d4SGreg Roach            ->map(User::rowMapper());
237e5a6b4d4SGreg Roach    }
238e5a6b4d4SGreg Roach
239e5a6b4d4SGreg Roach    /**
240e5a6b4d4SGreg Roach     * Get a list of all moderators.
241e5a6b4d4SGreg Roach     *
242*b5c8fd7eSGreg Roach     * @return Collection<User>
243e5a6b4d4SGreg Roach     */
244e5a6b4d4SGreg Roach    public function moderators(): Collection
245e5a6b4d4SGreg Roach    {
246e5a6b4d4SGreg Roach        return DB::table('user')
2471ab2f386SGreg Roach            ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id')
2487c4add84SGreg Roach            ->where('user_gedcom_setting.setting_name', '=', User::PREF_TREE_ROLE)
2497c4add84SGreg Roach            ->where('user_gedcom_setting.setting_value', '=', User::ROLE_MODERATOR)
250e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
2511ab2f386SGreg Roach            ->groupBy(['user.user_id'])
252e5a6b4d4SGreg Roach            ->orderBy('real_name')
253e5a6b4d4SGreg Roach            ->select(['user.*'])
254e5a6b4d4SGreg Roach            ->get()
255e5a6b4d4SGreg Roach            ->map(User::rowMapper());
256e5a6b4d4SGreg Roach    }
257e5a6b4d4SGreg Roach
258e5a6b4d4SGreg Roach    /**
259e5a6b4d4SGreg Roach     * Get a list of all verified users.
260e5a6b4d4SGreg Roach     *
261*b5c8fd7eSGreg Roach     * @return Collection<User>
262e5a6b4d4SGreg Roach     */
263e5a6b4d4SGreg Roach    public function unapproved(): Collection
264e5a6b4d4SGreg Roach    {
265e5a6b4d4SGreg Roach        return DB::table('user')
2667c4add84SGreg Roach            ->leftJoin('user_setting', static function (JoinClause $join): void {
2677c4add84SGreg Roach                $join
2687c4add84SGreg Roach                    ->on('user_setting.user_id', '=', 'user.user_id')
2697c4add84SGreg Roach                    ->where('user_setting.setting_name', '=', User::PREF_IS_ACCOUNT_APPROVED);
2707c4add84SGreg Roach            })
2717c4add84SGreg Roach            ->where(static function (Builder $query): void {
2727c4add84SGreg Roach                $query
2731ab2f386SGreg Roach                    ->where('user_setting.setting_value', '<>', '1')
2747c4add84SGreg Roach                    ->orWhereNull('user_setting.setting_value');
2757c4add84SGreg Roach            })
276e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
277e5a6b4d4SGreg Roach            ->orderBy('real_name')
278090fa720SGreg Roach            ->select(['user.*'])
279e5a6b4d4SGreg Roach            ->get()
280e5a6b4d4SGreg Roach            ->map(User::rowMapper());
281e5a6b4d4SGreg Roach    }
282e5a6b4d4SGreg Roach
283e5a6b4d4SGreg Roach    /**
284e5a6b4d4SGreg Roach     * Get a list of all verified users.
285e5a6b4d4SGreg Roach     *
286*b5c8fd7eSGreg Roach     * @return Collection<User>
287e5a6b4d4SGreg Roach     */
288e5a6b4d4SGreg Roach    public function unverified(): Collection
289e5a6b4d4SGreg Roach    {
290e5a6b4d4SGreg Roach        return DB::table('user')
2917c4add84SGreg Roach            ->leftJoin('user_setting', static function (JoinClause $join): void {
2927c4add84SGreg Roach                $join
2937c4add84SGreg Roach                    ->on('user_setting.user_id', '=', 'user.user_id')
2947c4add84SGreg Roach                    ->where('user_setting.setting_name', '=', User::PREF_IS_EMAIL_VERIFIED);
2957c4add84SGreg Roach            })
2967c4add84SGreg Roach            ->where(static function (Builder $query): void {
2977c4add84SGreg Roach                $query
2981ab2f386SGreg Roach                    ->where('user_setting.setting_value', '<>', '1')
2997c4add84SGreg Roach                    ->orWhereNull('user_setting.setting_value');
3007c4add84SGreg Roach            })
301e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
302e5a6b4d4SGreg Roach            ->orderBy('real_name')
303090fa720SGreg Roach            ->select(['user.*'])
304e5a6b4d4SGreg Roach            ->get()
305e5a6b4d4SGreg Roach            ->map(User::rowMapper());
306e5a6b4d4SGreg Roach    }
307e5a6b4d4SGreg Roach
308e5a6b4d4SGreg Roach    /**
309e5a6b4d4SGreg Roach     * Get a list of all users who are currently logged in.
310e5a6b4d4SGreg Roach     *
311*b5c8fd7eSGreg Roach     * @return Collection<User>
312e5a6b4d4SGreg Roach     */
313e5a6b4d4SGreg Roach    public function allLoggedIn(): Collection
314e5a6b4d4SGreg Roach    {
315e5a6b4d4SGreg Roach        return DB::table('user')
316e5a6b4d4SGreg Roach            ->join('session', 'session.user_id', '=', 'user.user_id')
317e5a6b4d4SGreg Roach            ->where('user.user_id', '>', 0)
318e5a6b4d4SGreg Roach            ->orderBy('real_name')
319e5a6b4d4SGreg Roach            ->select(['user.*'])
320e5a6b4d4SGreg Roach            ->distinct()
321e5a6b4d4SGreg Roach            ->get()
322e5a6b4d4SGreg Roach            ->map(User::rowMapper());
323e5a6b4d4SGreg Roach    }
324e5a6b4d4SGreg Roach
325e5a6b4d4SGreg Roach    /**
326e5a6b4d4SGreg Roach     * Create a new user.
327e5a6b4d4SGreg Roach     * The calling code needs to check for duplicates identifiers before calling
328e5a6b4d4SGreg Roach     * this function.
329e5a6b4d4SGreg Roach     *
330e5a6b4d4SGreg Roach     * @param string $user_name
331e5a6b4d4SGreg Roach     * @param string $real_name
332e5a6b4d4SGreg Roach     * @param string $email
333e5a6b4d4SGreg Roach     * @param string $password
334e5a6b4d4SGreg Roach     *
335e5a6b4d4SGreg Roach     * @return User
336e5a6b4d4SGreg Roach     */
3376be338f5SGreg Roach    public function create(string $user_name, string $real_name, string $email, string $password): User
338e5a6b4d4SGreg Roach    {
339e5a6b4d4SGreg Roach        DB::table('user')->insert([
340e5a6b4d4SGreg Roach            'user_name' => $user_name,
341e5a6b4d4SGreg Roach            'real_name' => $real_name,
342e5a6b4d4SGreg Roach            'email'     => $email,
343e5a6b4d4SGreg Roach            'password'  => password_hash($password, PASSWORD_DEFAULT),
344e5a6b4d4SGreg Roach        ]);
345e5a6b4d4SGreg Roach
346e5a6b4d4SGreg Roach        $user_id = (int) DB::connection()->getPdo()->lastInsertId();
347e5a6b4d4SGreg Roach
348e5a6b4d4SGreg Roach        return new User($user_id, $user_name, $real_name, $email);
349e5a6b4d4SGreg Roach    }
350e5a6b4d4SGreg Roach
351e5a6b4d4SGreg Roach    /**
352e5a6b4d4SGreg Roach     * Delete a user
353e5a6b4d4SGreg Roach     *
354e5a6b4d4SGreg Roach     * @param User $user
355e5a6b4d4SGreg Roach     *
356e5a6b4d4SGreg Roach     * @return void
357e5a6b4d4SGreg Roach     */
358e364afe4SGreg Roach    public function delete(User $user): void
359e5a6b4d4SGreg Roach    {
360e5a6b4d4SGreg Roach        // Don't delete the logs, just set the user to null.
361e5a6b4d4SGreg Roach        DB::table('log')
362e5a6b4d4SGreg Roach            ->where('user_id', '=', $user->id())
363e5a6b4d4SGreg Roach            ->update(['user_id' => null]);
364e5a6b4d4SGreg Roach
365e5a6b4d4SGreg Roach        // Take over the user’s pending changes. (What else could we do with them?)
366e5a6b4d4SGreg Roach        DB::table('change')
367e5a6b4d4SGreg Roach            ->where('user_id', '=', $user->id())
368e5a6b4d4SGreg Roach            ->where('status', '=', 'rejected')
369e5a6b4d4SGreg Roach            ->delete();
370e5a6b4d4SGreg Roach
371e5a6b4d4SGreg Roach        DB::table('change')
372e5a6b4d4SGreg Roach            ->where('user_id', '=', $user->id())
373e5a6b4d4SGreg Roach            ->update(['user_id' => Auth::id()]);
374e5a6b4d4SGreg Roach
375e5a6b4d4SGreg Roach        // Delete settings and preferences
376e5a6b4d4SGreg Roach        DB::table('block_setting')
377e5a6b4d4SGreg Roach            ->join('block', 'block_setting.block_id', '=', 'block.block_id')
378e5a6b4d4SGreg Roach            ->where('user_id', '=', $user->id())
379e5a6b4d4SGreg Roach            ->delete();
380e5a6b4d4SGreg Roach
381e5a6b4d4SGreg Roach        DB::table('block')->where('user_id', '=', $user->id())->delete();
382e5a6b4d4SGreg Roach        DB::table('user_gedcom_setting')->where('user_id', '=', $user->id())->delete();
383e5a6b4d4SGreg Roach        DB::table('user_setting')->where('user_id', '=', $user->id())->delete();
384e5a6b4d4SGreg Roach        DB::table('message')->where('user_id', '=', $user->id())->delete();
385e5a6b4d4SGreg Roach        DB::table('user')->where('user_id', '=', $user->id())->delete();
386e5a6b4d4SGreg Roach    }
38786730b84SGreg Roach
38886730b84SGreg Roach    /**
3894db4b4a9SGreg Roach     * @param User                   $contact_user
390a992e8c1SGreg Roach     * @param ServerRequestInterface $request
39186730b84SGreg Roach     *
39286730b84SGreg Roach     * @return string
39386730b84SGreg Roach     */
394a992e8c1SGreg Roach    public function contactLink(User $contact_user, ServerRequestInterface $request): string
395dcbe9044SGreg Roach    {
396a992e8c1SGreg Roach        $tree = $request->getAttribute('tree');
39775964c75SGreg Roach        assert($tree instanceof Tree);
3985229eadeSGreg Roach
399a992e8c1SGreg Roach        $user = $request->getAttribute('user');
40086730b84SGreg Roach
4017c4add84SGreg Roach        if ($contact_user->getPreference(User::PREF_CONTACT_METHOD) === 'mailto') {
40286730b84SGreg Roach            $url = 'mailto:' . $contact_user->email();
40386730b84SGreg Roach        } elseif ($user instanceof User) {
40486730b84SGreg Roach            // Logged-in users send direct messages
4050bf22806SGreg Roach            $url = route(MessagePage::class, [
4060bf22806SGreg Roach                'to' => $contact_user->userName(),
4070bf22806SGreg Roach                'tree' => $tree->name(),
4080bf22806SGreg Roach                'url'  => (string) $request->getUri(),
4090bf22806SGreg Roach            ]);
41086730b84SGreg Roach        } else {
41186730b84SGreg Roach            // Visitors use the contact form.
412e381f98dSGreg Roach            $url = route(ContactPage::class, [
41386730b84SGreg Roach                'to'   => $contact_user->userName(),
414d72b284aSGreg Roach                'tree' => $tree->name(),
415f567c3d8SGreg Roach                'url'  => (string) $request->getUri(),
41686730b84SGreg Roach            ]);
41786730b84SGreg Roach        }
41886730b84SGreg Roach
41986730b84SGreg Roach        return '<a href="' . e($url) . '" dir="auto">' . e($contact_user->realName()) . '</a>';
42086730b84SGreg Roach    }
421e5a6b4d4SGreg Roach}
422