xref: /webtrees/app/Statistics/Repository/UserRepository.php (revision 06f42609e3f1764a2e55be21f0ce941f29f42167)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Statistics\Repository;
21
22use Fisharebest\Webtrees\Auth;
23use Fisharebest\Webtrees\Contracts\UserInterface;
24use Fisharebest\Webtrees\I18N;
25use Fisharebest\Webtrees\Individual;
26use Fisharebest\Webtrees\Services\UserService;
27use Fisharebest\Webtrees\Statistics\Repository\Interfaces\UserRepositoryInterface;
28use Fisharebest\Webtrees\Tree;
29
30use function count;
31
32/**
33 * A repository providing methods for user related statistics.
34 */
35class UserRepository implements UserRepositoryInterface
36{
37    /**
38     * @var Tree
39     */
40    private $tree;
41    /**
42     * @var UserService
43     */
44    private $user_service;
45
46    /**
47     * Constructor.
48     *
49     * @param Tree        $tree
50     * @param UserService $user_service
51     */
52    public function __construct(Tree $tree, UserService $user_service)
53    {
54        $this->tree         = $tree;
55        $this->user_service = $user_service;
56    }
57
58    /**
59     * Who is currently logged in?
60     *
61     * @param string $type "list" or "nolist"
62     *
63     * @return string
64     */
65    private function usersLoggedInQuery($type = 'nolist'): string
66    {
67        $content   = '';
68        $anonymous = 0;
69        $logged_in = [];
70
71        foreach ($this->user_service->allLoggedIn() as $user) {
72            if (Auth::isAdmin() || $user->getPreference('visibleonline')) {
73                $logged_in[] = $user;
74            } else {
75                $anonymous++;
76            }
77        }
78
79        $count_logged_in = count($logged_in);
80
81        if ($count_logged_in === 0 && $anonymous === 0) {
82            $content .= I18N::translate('No signed-in and no anonymous users');
83        }
84
85        if ($anonymous > 0) {
86            $content .= '<b>' . I18N::plural('%s anonymous signed-in user', '%s anonymous signed-in users', $anonymous, I18N::number($anonymous)) . '</b>';
87        }
88
89        if ($count_logged_in > 0) {
90            if ($anonymous) {
91                if ($type === 'list') {
92                    $content .= '<br><br>';
93                } else {
94                    $content .= ' ' . I18N::translate('and') . ' ';
95                }
96            }
97            $content .= '<b>' . I18N::plural('%s signed-in user', '%s signed-in users', $count_logged_in, I18N::number($count_logged_in)) . '</b>';
98            if ($type === 'list') {
99                $content .= '<ul>';
100            } else {
101                $content .= ': ';
102            }
103        }
104
105        if (Auth::check()) {
106            foreach ($logged_in as $user) {
107                if ($type === 'list') {
108                    $content .= '<li>';
109                }
110
111                $individual = Individual::getInstance($this->tree->getUserPreference($user, 'gedcomid'), $this->tree);
112
113                if ($individual instanceof Individual && $individual->canShow()) {
114                    $content .= '<a href="' . e($individual->url()) . '">' . e($user->realName()) . '</a>';
115                } else {
116                    $content .= e($user->realName());
117                }
118
119                $content .= ' - ' . e($user->userName());
120
121                if (($user->getPreference('contactmethod') !== 'none') && (Auth::id() !== $user->id())) {
122                    if ($type === 'list') {
123                        $content .= '<br>';
124                    }
125                    $content .= '<a href="' . e(route('message', ['to' => $user->userName(), 'tree' => $this->tree->name()])) . '" class="btn btn-link" title="' . I18N::translate('Send a message') . '">' . view('icons/email') . '</a>';
126                }
127
128                if ($type === 'list') {
129                    $content .= '</li>';
130                }
131            }
132        }
133
134        if ($type === 'list') {
135            $content .= '</ul>';
136        }
137
138        return $content;
139    }
140
141    /**
142     * @inheritDoc
143     */
144    public function usersLoggedIn(): string
145    {
146        return $this->usersLoggedInQuery('nolist');
147    }
148
149    /**
150     * @inheritDoc
151     */
152    public function usersLoggedInList(): string
153    {
154        return $this->usersLoggedInQuery('list');
155    }
156
157    /**
158     * Returns true if the given user is visible to others.
159     *
160     * @param UserInterface $user
161     *
162     * @return bool
163     */
164    private function isUserVisible(UserInterface $user): bool
165    {
166        return Auth::isAdmin() || $user->getPreference('visibleonline');
167    }
168
169    /**
170     * @inheritDoc
171     */
172    public function usersLoggedInTotal(): int
173    {
174        return count($this->user_service->allLoggedIn());
175    }
176
177    /**
178     * @inheritDoc
179     */
180    public function usersLoggedInTotalAnon(): int
181    {
182        $anonymous = 0;
183
184        foreach ($this->user_service->allLoggedIn() as $user) {
185            if (!$this->isUserVisible($user)) {
186                ++$anonymous;
187            }
188        }
189
190        return $anonymous;
191    }
192
193    /**
194     * @inheritDoc
195     */
196    public function usersLoggedInTotalVisible(): int
197    {
198        $visible = 0;
199
200        foreach ($this->user_service->allLoggedIn() as $user) {
201            if ($this->isUserVisible($user)) {
202                ++$visible;
203            }
204        }
205
206        return $visible;
207    }
208
209    /**
210     * @inheritDoc
211     */
212    public function userId(): string
213    {
214        return (string) Auth::id();
215    }
216
217    /**
218     * @inheritDoc
219     */
220    public function userName(string $visitor_text = ''): string
221    {
222        if (Auth::check()) {
223            return e(Auth::user()->userName());
224        }
225
226        // if #username:visitor# was specified, then "visitor" will be returned when the user is not logged in
227        return e($visitor_text);
228    }
229
230    /**
231     * @inheritDoc
232     */
233    public function userFullName(): string
234    {
235        return Auth::check() ? '<span dir="auto">' . e(Auth::user()->realName()) . '</span>' : '';
236    }
237
238    /**
239     * Returns the user count.
240     *
241     * @return int
242     */
243    private function getUserCount(): int
244    {
245        return count($this->user_service->all());
246    }
247
248    /**
249     * Returns the administrator count.
250     *
251     * @return int
252     */
253    private function getAdminCount(): int
254    {
255        return count($this->user_service->administrators());
256    }
257
258    /**
259     * @inheritDoc
260     */
261    public function totalUsers(): string
262    {
263        return I18N::number($this->getUserCount());
264    }
265
266    /**
267     * @inheritDoc
268     */
269    public function totalAdmins(): string
270    {
271        return I18N::number($this->getAdminCount());
272    }
273
274    /**
275     * @inheritDoc
276     */
277    public function totalNonAdmins(): string
278    {
279        return I18N::number($this->getUserCount() - $this->getAdminCount());
280    }
281}
282