18add1155SRico Sonntag<?php 23976b470SGreg Roach 38add1155SRico Sonntag/** 48add1155SRico Sonntag * webtrees: online genealogy 50dcd9387SGreg Roach * Copyright (C) 2020 webtrees development team 68add1155SRico Sonntag * This program is free software: you can redistribute it and/or modify 78add1155SRico Sonntag * it under the terms of the GNU General Public License as published by 88add1155SRico Sonntag * the Free Software Foundation, either version 3 of the License, or 98add1155SRico Sonntag * (at your option) any later version. 108add1155SRico Sonntag * This program is distributed in the hope that it will be useful, 118add1155SRico Sonntag * but WITHOUT ANY WARRANTY; without even the implied warranty of 128add1155SRico Sonntag * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138add1155SRico Sonntag * GNU General Public License for more details. 148add1155SRico Sonntag * You should have received a copy of the GNU General Public License 158add1155SRico Sonntag * along with this program. If not, see <http://www.gnu.org/licenses/>. 168add1155SRico Sonntag */ 17fcfa147eSGreg Roach 188add1155SRico Sonntagdeclare(strict_types=1); 198add1155SRico Sonntag 208add1155SRico Sonntagnamespace Fisharebest\Webtrees\Statistics\Repository; 218add1155SRico Sonntag 228add1155SRico Sonntaguse Fisharebest\Webtrees\Auth; 23e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 24*6b9cb339SGreg Roachuse Fisharebest\Webtrees\Registry; 25e381f98dSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MessagePage; 268add1155SRico Sonntaguse Fisharebest\Webtrees\I18N; 27c0112ce8SGreg Roachuse Fisharebest\Webtrees\Individual; 28e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 298add1155SRico Sonntaguse Fisharebest\Webtrees\Statistics\Repository\Interfaces\UserRepositoryInterface; 308add1155SRico Sonntaguse Fisharebest\Webtrees\Tree; 317c4add84SGreg Roachuse Fisharebest\Webtrees\User; 328add1155SRico Sonntag 3371378461SGreg Roachuse function count; 3471378461SGreg Roach 358add1155SRico Sonntag/** 368add1155SRico Sonntag * A repository providing methods for user related statistics. 378add1155SRico Sonntag */ 388add1155SRico Sonntagclass UserRepository implements UserRepositoryInterface 398add1155SRico Sonntag{ 408add1155SRico Sonntag /** 418add1155SRico Sonntag * @var Tree 428add1155SRico Sonntag */ 438add1155SRico Sonntag private $tree; 44e5a6b4d4SGreg Roach /** 45e5a6b4d4SGreg Roach * @var UserService 46e5a6b4d4SGreg Roach */ 47e5a6b4d4SGreg Roach private $user_service; 488add1155SRico Sonntag 498add1155SRico Sonntag /** 508add1155SRico Sonntag * Constructor. 518add1155SRico Sonntag * 528add1155SRico Sonntag * @param Tree $tree 53e5a6b4d4SGreg Roach * @param UserService $user_service 548add1155SRico Sonntag */ 55e5a6b4d4SGreg Roach public function __construct(Tree $tree, UserService $user_service) 568add1155SRico Sonntag { 578add1155SRico Sonntag $this->tree = $tree; 58e5a6b4d4SGreg Roach $this->user_service = $user_service; 598add1155SRico Sonntag } 608add1155SRico Sonntag 618add1155SRico Sonntag /** 628add1155SRico Sonntag * Who is currently logged in? 638add1155SRico Sonntag * 64c0112ce8SGreg Roach * @param string $type "list" or "nolist" 658add1155SRico Sonntag * 668add1155SRico Sonntag * @return string 678add1155SRico Sonntag */ 688add1155SRico Sonntag private function usersLoggedInQuery($type = 'nolist'): string 698add1155SRico Sonntag { 708add1155SRico Sonntag $content = ''; 71c0112ce8SGreg Roach $anonymous = 0; 72c0112ce8SGreg Roach $logged_in = []; 738add1155SRico Sonntag 74e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 757c4add84SGreg Roach if (Auth::isAdmin() || $user->getPreference(User::PREF_IS_VISIBLE_ONLINE) === '1') { 76c0112ce8SGreg Roach $logged_in[] = $user; 778add1155SRico Sonntag } else { 78c0112ce8SGreg Roach $anonymous++; 798add1155SRico Sonntag } 808add1155SRico Sonntag } 818add1155SRico Sonntag 826ccdf4f0SGreg Roach $count_logged_in = count($logged_in); 83c0112ce8SGreg Roach 84c0112ce8SGreg Roach if ($count_logged_in === 0 && $anonymous === 0) { 85c0112ce8SGreg Roach $content .= I18N::translate('No signed-in and no anonymous users'); 868add1155SRico Sonntag } 878add1155SRico Sonntag 88c0112ce8SGreg Roach if ($anonymous > 0) { 89c0112ce8SGreg Roach $content .= '<b>' . I18N::plural('%s anonymous signed-in user', '%s anonymous signed-in users', $anonymous, I18N::number($anonymous)) . '</b>'; 908add1155SRico Sonntag } 918add1155SRico Sonntag 92c0112ce8SGreg Roach if ($count_logged_in > 0) { 93c0112ce8SGreg Roach if ($anonymous) { 948add1155SRico Sonntag if ($type === 'list') { 958add1155SRico Sonntag $content .= '<br><br>'; 968add1155SRico Sonntag } else { 978add1155SRico Sonntag $content .= ' ' . I18N::translate('and') . ' '; 988add1155SRico Sonntag } 998add1155SRico Sonntag } 100c0112ce8SGreg Roach $content .= '<b>' . I18N::plural('%s signed-in user', '%s signed-in users', $count_logged_in, I18N::number($count_logged_in)) . '</b>'; 1018add1155SRico Sonntag if ($type === 'list') { 1028add1155SRico Sonntag $content .= '<ul>'; 1038add1155SRico Sonntag } else { 1048add1155SRico Sonntag $content .= ': '; 1058add1155SRico Sonntag } 1068add1155SRico Sonntag } 1078add1155SRico Sonntag 1088add1155SRico Sonntag if (Auth::check()) { 109c0112ce8SGreg Roach foreach ($logged_in as $user) { 1108add1155SRico Sonntag if ($type === 'list') { 111c0112ce8SGreg Roach $content .= '<li>'; 1128add1155SRico Sonntag } 1138add1155SRico Sonntag 114*6b9cb339SGreg Roach $individual = Registry::individualFactory()->make($this->tree->getUserPreference($user, User::PREF_TREE_ACCOUNT_XREF), $this->tree); 115c0112ce8SGreg Roach 116c0112ce8SGreg Roach if ($individual instanceof Individual && $individual->canShow()) { 117c0112ce8SGreg Roach $content .= '<a href="' . e($individual->url()) . '">' . e($user->realName()) . '</a>'; 118c0112ce8SGreg Roach } else { 119c0112ce8SGreg Roach $content .= e($user->realName()); 120c0112ce8SGreg Roach } 121c0112ce8SGreg Roach 122c0112ce8SGreg Roach $content .= ' - ' . e($user->userName()); 123c0112ce8SGreg Roach 1247c4add84SGreg Roach if (($user->getPreference(User::PREF_CONTACT_METHOD) !== 'none') && (Auth::id() !== $user->id())) { 1258add1155SRico Sonntag if ($type === 'list') { 1268add1155SRico Sonntag $content .= '<br>'; 1278add1155SRico Sonntag } 128e381f98dSGreg Roach $content .= '<a href="' . e(route(MessagePage::class, ['to' => $user->userName(), 'tree' => $this->tree->name()])) . '" class="btn btn-link" title="' . I18N::translate('Send a message') . '">' . view('icons/email') . '</a>'; 1298add1155SRico Sonntag } 1308add1155SRico Sonntag 1318add1155SRico Sonntag if ($type === 'list') { 1328add1155SRico Sonntag $content .= '</li>'; 1338add1155SRico Sonntag } 1348add1155SRico Sonntag } 1358add1155SRico Sonntag } 1368add1155SRico Sonntag 1378add1155SRico Sonntag if ($type === 'list') { 1388add1155SRico Sonntag $content .= '</ul>'; 1398add1155SRico Sonntag } 1408add1155SRico Sonntag 1418add1155SRico Sonntag return $content; 1428add1155SRico Sonntag } 1438add1155SRico Sonntag 1448add1155SRico Sonntag /** 1450dcd9387SGreg Roach * @return string 1468add1155SRico Sonntag */ 1478add1155SRico Sonntag public function usersLoggedIn(): string 1488add1155SRico Sonntag { 149c0112ce8SGreg Roach return $this->usersLoggedInQuery('nolist'); 1508add1155SRico Sonntag } 1518add1155SRico Sonntag 1528add1155SRico Sonntag /** 1530dcd9387SGreg Roach * @return string 1548add1155SRico Sonntag */ 1558add1155SRico Sonntag public function usersLoggedInList(): string 1568add1155SRico Sonntag { 1578add1155SRico Sonntag return $this->usersLoggedInQuery('list'); 1588add1155SRico Sonntag } 1598add1155SRico Sonntag 1608add1155SRico Sonntag /** 1618add1155SRico Sonntag * Returns true if the given user is visible to others. 1628add1155SRico Sonntag * 163e5a6b4d4SGreg Roach * @param UserInterface $user 1648add1155SRico Sonntag * 1658add1155SRico Sonntag * @return bool 1668add1155SRico Sonntag */ 167e5a6b4d4SGreg Roach private function isUserVisible(UserInterface $user): bool 1688add1155SRico Sonntag { 1697c4add84SGreg Roach return Auth::isAdmin() || $user->getPreference(User::PREF_IS_VISIBLE_ONLINE) === '1'; 1708add1155SRico Sonntag } 1718add1155SRico Sonntag 1728add1155SRico Sonntag /** 1730dcd9387SGreg Roach * @return int 1748add1155SRico Sonntag */ 1758add1155SRico Sonntag public function usersLoggedInTotal(): int 1768add1155SRico Sonntag { 1776ccdf4f0SGreg Roach return count($this->user_service->allLoggedIn()); 1788add1155SRico Sonntag } 1798add1155SRico Sonntag 1808add1155SRico Sonntag /** 1810dcd9387SGreg Roach * @return int 1828add1155SRico Sonntag */ 1838add1155SRico Sonntag public function usersLoggedInTotalAnon(): int 1848add1155SRico Sonntag { 1858add1155SRico Sonntag $anonymous = 0; 1868add1155SRico Sonntag 187e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 1888add1155SRico Sonntag if (!$this->isUserVisible($user)) { 1898add1155SRico Sonntag ++$anonymous; 1908add1155SRico Sonntag } 1918add1155SRico Sonntag } 1928add1155SRico Sonntag 1938add1155SRico Sonntag return $anonymous; 1948add1155SRico Sonntag } 1958add1155SRico Sonntag 1968add1155SRico Sonntag /** 1970dcd9387SGreg Roach * @return int 1988add1155SRico Sonntag */ 1998add1155SRico Sonntag public function usersLoggedInTotalVisible(): int 2008add1155SRico Sonntag { 2018add1155SRico Sonntag $visible = 0; 2028add1155SRico Sonntag 203e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 2048add1155SRico Sonntag if ($this->isUserVisible($user)) { 2058add1155SRico Sonntag ++$visible; 2068add1155SRico Sonntag } 2078add1155SRico Sonntag } 2088add1155SRico Sonntag 2098add1155SRico Sonntag return $visible; 2108add1155SRico Sonntag } 2118add1155SRico Sonntag 2128add1155SRico Sonntag /** 2130dcd9387SGreg Roach * @return string 2148add1155SRico Sonntag */ 2158add1155SRico Sonntag public function userId(): string 2168add1155SRico Sonntag { 2178add1155SRico Sonntag return (string) Auth::id(); 2188add1155SRico Sonntag } 2198add1155SRico Sonntag 2208add1155SRico Sonntag /** 2210dcd9387SGreg Roach * @param string $visitor_text 2220dcd9387SGreg Roach * 2230dcd9387SGreg Roach * @return string 2248add1155SRico Sonntag */ 2258add1155SRico Sonntag public function userName(string $visitor_text = ''): string 2268add1155SRico Sonntag { 2278add1155SRico Sonntag if (Auth::check()) { 228e5a6b4d4SGreg Roach return e(Auth::user()->userName()); 2298add1155SRico Sonntag } 2308add1155SRico Sonntag 2318add1155SRico Sonntag // if #username:visitor# was specified, then "visitor" will be returned when the user is not logged in 2328add1155SRico Sonntag return e($visitor_text); 2338add1155SRico Sonntag } 2348add1155SRico Sonntag 2358add1155SRico Sonntag /** 2360dcd9387SGreg Roach * @return string 2378add1155SRico Sonntag */ 2388add1155SRico Sonntag public function userFullName(): string 2398add1155SRico Sonntag { 240e5a6b4d4SGreg Roach return Auth::check() ? '<span dir="auto">' . e(Auth::user()->realName()) . '</span>' : ''; 2418add1155SRico Sonntag } 2428add1155SRico Sonntag 2438add1155SRico Sonntag /** 2448add1155SRico Sonntag * Returns the user count. 2458add1155SRico Sonntag * 2468add1155SRico Sonntag * @return int 2478add1155SRico Sonntag */ 2488add1155SRico Sonntag private function getUserCount(): int 2498add1155SRico Sonntag { 2506ccdf4f0SGreg Roach return count($this->user_service->all()); 2518add1155SRico Sonntag } 2528add1155SRico Sonntag 2538add1155SRico Sonntag /** 2548add1155SRico Sonntag * Returns the administrator count. 2558add1155SRico Sonntag * 2568add1155SRico Sonntag * @return int 2578add1155SRico Sonntag */ 2588add1155SRico Sonntag private function getAdminCount(): int 2598add1155SRico Sonntag { 2606ccdf4f0SGreg Roach return count($this->user_service->administrators()); 2618add1155SRico Sonntag } 2628add1155SRico Sonntag 2638add1155SRico Sonntag /** 2640dcd9387SGreg Roach * @return string 2658add1155SRico Sonntag */ 2668add1155SRico Sonntag public function totalUsers(): string 2678add1155SRico Sonntag { 2688add1155SRico Sonntag return I18N::number($this->getUserCount()); 2698add1155SRico Sonntag } 2708add1155SRico Sonntag 2718add1155SRico Sonntag /** 2720dcd9387SGreg Roach * @return string 2738add1155SRico Sonntag */ 2748add1155SRico Sonntag public function totalAdmins(): string 2758add1155SRico Sonntag { 2768add1155SRico Sonntag return I18N::number($this->getAdminCount()); 2778add1155SRico Sonntag } 2788add1155SRico Sonntag 2798add1155SRico Sonntag /** 2800dcd9387SGreg Roach * @return string 2818add1155SRico Sonntag */ 2828add1155SRico Sonntag public function totalNonAdmins(): string 2838add1155SRico Sonntag { 2848add1155SRico Sonntag return I18N::number($this->getUserCount() - $this->getAdminCount()); 2858add1155SRico Sonntag } 2868add1155SRico Sonntag} 287