Passed
Push — master ( 502cab...a00bcc )
by Greg
05:16
created

UserService::findByToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 13
rs 9.9
1
<?php
2
/**
3
 * webtrees: online genealogy
4
 * Copyright (C) 2019 webtrees development team
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 * GNU General Public License for more details.
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15
 */
16
declare(strict_types=1);
17
18
namespace Fisharebest\Webtrees\Services;
19
20
use Fisharebest\Webtrees\Auth;
21
use Fisharebest\Webtrees\Carbon;
22
use Fisharebest\Webtrees\Contracts\UserInterface;
23
use Fisharebest\Webtrees\Individual;
24
use Fisharebest\Webtrees\Tree;
25
use Fisharebest\Webtrees\User;
26
use Illuminate\Database\Capsule\Manager as DB;
27
use Illuminate\Database\Query\JoinClause;
28
use Illuminate\Support\Collection;
29
use Psr\Http\Message\ServerRequestInterface;
30
use function app;
31
32
/**
33
 * Functions for managing users.
34
 */
35
class UserService
36
{
37
    /**
38
     * Find the user with a specified user_id.
39
     *
40
     * @param int|null $user_id
41
     *
42
     * @return User|null
43
     */
44
    public function find($user_id): ?User
45
    {
46
        return app('cache.array')->rememberForever(__CLASS__ . $user_id, static function () use ($user_id): ?User {
47
            return DB::table('user')
48
                ->where('user_id', '=', $user_id)
49
                ->get()
50
                ->map(User::rowMapper())
51
                ->first();
52
        });
53
    }
54
55
    /**
56
     * Find the user with a specified email address.
57
     *
58
     * @param string $email
59
     *
60
     * @return User|null
61
     */
62
    public function findByEmail($email): ?User
63
    {
64
        return DB::table('user')
65
            ->where('email', '=', $email)
66
            ->get()
67
            ->map(User::rowMapper())
68
            ->first();
69
    }
70
71
    /**
72
     * Find the user with a specified user_name or email address.
73
     *
74
     * @param string $identifier
75
     *
76
     * @return User|null
77
     */
78
    public function findByIdentifier($identifier): ?User
79
    {
80
        return DB::table('user')
81
            ->where('user_name', '=', $identifier)
82
            ->orWhere('email', '=', $identifier)
83
            ->get()
84
            ->map(User::rowMapper())
85
            ->first();
86
    }
87
88
    /**
89
     * Find the user(s) with a specified genealogy record.
90
     *
91
     * @param Individual $individual
92
     *
93
     * @return Collection
94
     */
95
    public function findByIndividual(Individual $individual): Collection
96
    {
97
        return DB::table('user')
98
            ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id')
99
            ->where('gedcom_id', '=', $individual->tree()->id())
100
            ->where('setting_value', '=', $individual->xref())
101
            ->where('setting_name', '=', 'gedcomid')
102
            ->select(['user.*'])
103
            ->get()
104
            ->map(User::rowMapper());
105
    }
106
107
    /**
108
     * Find the user with a specified password reset token.
109
     *
110
     * @param string $token
111
     *
112
     * @return User|null
113
     */
114
    public function findByToken(string $token): ?User
115
    {
116
        return DB::table('user')
117
            ->join('user_setting AS us1', 'us1.user_id', '=', 'user.user_id')
118
            ->where('us1.setting_name', '=', 'password-token')
119
            ->where('us1.setting_value', '=', $token)
120
            ->join('user_setting AS us2', 'us2.user_id', '=', 'user.user_id')
121
            ->where('us2.setting_name', '=', 'password-token-expire')
122
            ->where('us2.setting_value', '>', Carbon::now()->timestamp)
123
            ->select(['user.*'])
124
            ->get()
125
            ->map(User::rowMapper())
126
            ->first();
127
    }
128
129
    /**
130
     * Find the user with a specified user_name.
131
     *
132
     * @param string $user_name
133
     *
134
     * @return User|null
135
     */
136
    public function findByUserName($user_name): ?User
137
    {
138
        return DB::table('user')
139
            ->where('user_name', '=', $user_name)
140
            ->get()
141
            ->map(User::rowMapper())
142
            ->first();
143
    }
144
145
    /**
146
     * Get a list of all users.
147
     *
148
     * @return Collection
149
     */
150
    public function all(): Collection
151
    {
152
        return DB::table('user')
153
            ->where('user_id', '>', 0)
154
            ->orderBy('real_name')
155
            ->get()
156
            ->map(User::rowMapper());
157
    }
158
159
    /**
160
     * Get a list of all administrators.
161
     *
162
     * @return Collection
163
     */
164
    public function administrators(): Collection
165
    {
166
        return DB::table('user')
167
            ->join('user_setting', static function (JoinClause $join): void {
168
                $join
169
                    ->on('user_setting.user_id', '=', 'user.user_id')
170
                    ->where('user_setting.setting_name', '=', 'canadmin')
171
                    ->where('user_setting.setting_value', '=', '1');
172
            })
173
            ->where('user.user_id', '>', 0)
174
            ->orderBy('real_name')
175
            ->select(['user.*'])
176
            ->get()
177
            ->map(User::rowMapper());
178
    }
179
180
    /**
181
     * Get a list of all managers.
182
     *
183
     * @return Collection
184
     */
185
    public function managers(): Collection
186
    {
187
        return DB::table('user')
188
            ->join('user_gedcom_setting', static function (JoinClause $join): void {
189
                $join
190
                    ->on('user_gedcom_setting.user_id', '=', 'user.user_id')
191
                    ->where('user_gedcom_setting.setting_name', '=', 'canedit')
192
                    ->where('user_gedcom_setting.setting_value', '=', 'admin');
193
            })
194
            ->where('user.user_id', '>', 0)
195
            ->orderBy('real_name')
196
            ->select(['user.*'])
197
            ->get()
198
            ->map(User::rowMapper());
199
    }
200
201
    /**
202
     * Get a list of all moderators.
203
     *
204
     * @return Collection
205
     */
206
    public function moderators(): Collection
207
    {
208
        return DB::table('user')
209
            ->join('user_gedcom_setting', static function (JoinClause $join): void {
210
                $join
211
                    ->on('user_gedcom_setting.user_id', '=', 'user.user_id')
212
                    ->where('user_gedcom_setting.setting_name', '=', 'canedit')
213
                    ->where('user_gedcom_setting.setting_value', '=', 'accept');
214
            })
215
            ->where('user.user_id', '>', 0)
216
            ->orderBy('real_name')
217
            ->select(['user.*'])
218
            ->get()
219
            ->map(User::rowMapper());
220
    }
221
222
    /**
223
     * Get a list of all verified users.
224
     *
225
     * @return Collection
226
     */
227
    public function unapproved(): Collection
228
    {
229
        return DB::table('user')
230
            ->join('user_setting', static function (JoinClause $join): void {
231
                $join
232
                    ->on('user_setting.user_id', '=', 'user.user_id')
233
                    ->where('user_setting.setting_name', '=', 'verified_by_admin')
234
                    ->where('user_setting.setting_value', '=', '0');
235
            })
236
            ->where('user.user_id', '>', 0)
237
            ->orderBy('real_name')
238
            ->select(['user.*'])
239
            ->get()
240
            ->map(User::rowMapper());
241
    }
242
243
    /**
244
     * Get a list of all verified users.
245
     *
246
     * @return Collection
247
     */
248
    public function unverified(): Collection
249
    {
250
        return DB::table('user')
251
            ->join('user_setting', static function (JoinClause $join): void {
252
                $join
253
                    ->on('user_setting.user_id', '=', 'user.user_id')
254
                    ->where('user_setting.setting_name', '=', 'verified')
255
                    ->where('user_setting.setting_value', '=', '0');
256
            })
257
            ->where('user.user_id', '>', 0)
258
            ->orderBy('real_name')
259
            ->select(['user.*'])
260
            ->get()
261
            ->map(User::rowMapper());
262
    }
263
264
    /**
265
     * Get a list of all users who are currently logged in.
266
     *
267
     * @return Collection
268
     */
269
    public function allLoggedIn(): Collection
270
    {
271
        return DB::table('user')
272
            ->join('session', 'session.user_id', '=', 'user.user_id')
273
            ->where('user.user_id', '>', 0)
274
            ->orderBy('real_name')
275
            ->select(['user.*'])
276
            ->distinct()
277
            ->get()
278
            ->map(User::rowMapper());
279
    }
280
281
    /**
282
     * Create a new user.
283
     * The calling code needs to check for duplicates identifiers before calling
284
     * this function.
285
     *
286
     * @param string $user_name
287
     * @param string $real_name
288
     * @param string $email
289
     * @param string $password
290
     *
291
     * @return User
292
     */
293
    public function create(string $user_name, string $real_name, string $email, string $password): User
294
    {
295
        DB::table('user')->insert([
296
            'user_name' => $user_name,
297
            'real_name' => $real_name,
298
            'email'     => $email,
299
            'password'  => password_hash($password, PASSWORD_DEFAULT),
300
        ]);
301
302
        $user_id = (int) DB::connection()->getPdo()->lastInsertId();
303
304
        return new User($user_id, $user_name, $real_name, $email);
305
    }
306
307
    /**
308
     * Delete a user
309
     *
310
     * @param User $user
311
     *
312
     * @return void
313
     */
314
    public function delete(User $user): void
315
    {
316
        // Don't delete the logs, just set the user to null.
317
        DB::table('log')
318
            ->where('user_id', '=', $user->id())
319
            ->update(['user_id' => null]);
320
321
        // Take over the user’s pending changes. (What else could we do with them?)
322
        DB::table('change')
323
            ->where('user_id', '=', $user->id())
324
            ->where('status', '=', 'rejected')
325
            ->delete();
326
327
        DB::table('change')
328
            ->where('user_id', '=', $user->id())
329
            ->update(['user_id' => Auth::id()]);
330
331
        // Delete settings and preferences
332
        DB::table('block_setting')
333
            ->join('block', 'block_setting.block_id', '=', 'block.block_id')
334
            ->where('user_id', '=', $user->id())
335
            ->delete();
336
337
        DB::table('block')->where('user_id', '=', $user->id())->delete();
338
        DB::table('user_gedcom_setting')->where('user_id', '=', $user->id())->delete();
339
        DB::table('user_setting')->where('user_id', '=', $user->id())->delete();
340
        DB::table('message')->where('user_id', '=', $user->id())->delete();
341
        DB::table('user')->where('user_id', '=', $user->id())->delete();
342
    }
343
344
    /**
345
     * @param User $contact_user
346
     *
347
     * @return string
348
     */
349
    public function contactLink(User $contact_user): string
350
    {
351
        $tree    = app(Tree::class);
352
        $user    = app(UserInterface::class);
353
        $request = app(ServerRequestInterface::class);
354
355
        if ($contact_user->getPreference('contactmethod') === 'mailto') {
356
            $url = 'mailto:' . $contact_user->email();
357
        } elseif ($user instanceof User) {
358
            // Logged-in users send direct messages
359
            $url = route('message', ['to' => $contact_user->userName()]);
360
        } else {
361
            // Visitors use the contact form.
362
            $url = route('contact', [
363
                'ged' => $tree ? $tree->name() : '',
0 ignored issues
show
introduced by
$tree is of type Fisharebest\Webtrees\Tree, thus it always evaluated to true.
Loading history...
364
                'to'  => $contact_user->userName(),
365
                'url' => $request->getAttribute('request_uri'),
366
            ]);
367
        }
368
369
        return '<a href="' . e($url) . '" dir="auto">' . e($contact_user->realName()) . '</a>';
370
    }
371
}
372