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