18add1155SRico Sonntag<?php 23976b470SGreg Roach 38add1155SRico Sonntag/** 48add1155SRico Sonntag * webtrees: online genealogy 5242a7862SGreg Roach * Copyright (C) 2019 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; 24e381f98dSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MessagePage; 258add1155SRico Sonntaguse Fisharebest\Webtrees\I18N; 26c0112ce8SGreg Roachuse Fisharebest\Webtrees\Individual; 27e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 288add1155SRico Sonntaguse Fisharebest\Webtrees\Statistics\Repository\Interfaces\UserRepositoryInterface; 298add1155SRico Sonntaguse Fisharebest\Webtrees\Tree; 30*7c4add84SGreg Roachuse Fisharebest\Webtrees\User; 318add1155SRico Sonntag 3271378461SGreg Roachuse function count; 3371378461SGreg Roach 348add1155SRico Sonntag/** 358add1155SRico Sonntag * A repository providing methods for user related statistics. 368add1155SRico Sonntag */ 378add1155SRico Sonntagclass UserRepository implements UserRepositoryInterface 388add1155SRico Sonntag{ 398add1155SRico Sonntag /** 408add1155SRico Sonntag * @var Tree 418add1155SRico Sonntag */ 428add1155SRico Sonntag private $tree; 43e5a6b4d4SGreg Roach /** 44e5a6b4d4SGreg Roach * @var UserService 45e5a6b4d4SGreg Roach */ 46e5a6b4d4SGreg Roach private $user_service; 478add1155SRico Sonntag 488add1155SRico Sonntag /** 498add1155SRico Sonntag * Constructor. 508add1155SRico Sonntag * 518add1155SRico Sonntag * @param Tree $tree 52e5a6b4d4SGreg Roach * @param UserService $user_service 538add1155SRico Sonntag */ 54e5a6b4d4SGreg Roach public function __construct(Tree $tree, UserService $user_service) 558add1155SRico Sonntag { 568add1155SRico Sonntag $this->tree = $tree; 57e5a6b4d4SGreg Roach $this->user_service = $user_service; 588add1155SRico Sonntag } 598add1155SRico Sonntag 608add1155SRico Sonntag /** 618add1155SRico Sonntag * Who is currently logged in? 628add1155SRico Sonntag * 63c0112ce8SGreg Roach * @param string $type "list" or "nolist" 648add1155SRico Sonntag * 658add1155SRico Sonntag * @return string 668add1155SRico Sonntag */ 678add1155SRico Sonntag private function usersLoggedInQuery($type = 'nolist'): string 688add1155SRico Sonntag { 698add1155SRico Sonntag $content = ''; 70c0112ce8SGreg Roach $anonymous = 0; 71c0112ce8SGreg Roach $logged_in = []; 728add1155SRico Sonntag 73e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 74*7c4add84SGreg Roach if (Auth::isAdmin() || $user->getPreference(User::PREF_IS_VISIBLE_ONLINE) === '1') { 75c0112ce8SGreg Roach $logged_in[] = $user; 768add1155SRico Sonntag } else { 77c0112ce8SGreg Roach $anonymous++; 788add1155SRico Sonntag } 798add1155SRico Sonntag } 808add1155SRico Sonntag 816ccdf4f0SGreg Roach $count_logged_in = count($logged_in); 82c0112ce8SGreg Roach 83c0112ce8SGreg Roach if ($count_logged_in === 0 && $anonymous === 0) { 84c0112ce8SGreg Roach $content .= I18N::translate('No signed-in and no anonymous users'); 858add1155SRico Sonntag } 868add1155SRico Sonntag 87c0112ce8SGreg Roach if ($anonymous > 0) { 88c0112ce8SGreg Roach $content .= '<b>' . I18N::plural('%s anonymous signed-in user', '%s anonymous signed-in users', $anonymous, I18N::number($anonymous)) . '</b>'; 898add1155SRico Sonntag } 908add1155SRico Sonntag 91c0112ce8SGreg Roach if ($count_logged_in > 0) { 92c0112ce8SGreg Roach if ($anonymous) { 938add1155SRico Sonntag if ($type === 'list') { 948add1155SRico Sonntag $content .= '<br><br>'; 958add1155SRico Sonntag } else { 968add1155SRico Sonntag $content .= ' ' . I18N::translate('and') . ' '; 978add1155SRico Sonntag } 988add1155SRico Sonntag } 99c0112ce8SGreg Roach $content .= '<b>' . I18N::plural('%s signed-in user', '%s signed-in users', $count_logged_in, I18N::number($count_logged_in)) . '</b>'; 1008add1155SRico Sonntag if ($type === 'list') { 1018add1155SRico Sonntag $content .= '<ul>'; 1028add1155SRico Sonntag } else { 1038add1155SRico Sonntag $content .= ': '; 1048add1155SRico Sonntag } 1058add1155SRico Sonntag } 1068add1155SRico Sonntag 1078add1155SRico Sonntag if (Auth::check()) { 108c0112ce8SGreg Roach foreach ($logged_in as $user) { 1098add1155SRico Sonntag if ($type === 'list') { 110c0112ce8SGreg Roach $content .= '<li>'; 1118add1155SRico Sonntag } 1128add1155SRico Sonntag 113*7c4add84SGreg Roach $individual = Individual::getInstance($this->tree->getUserPreference($user, User::PREF_TREE_ACCOUNT_XREF), $this->tree); 114c0112ce8SGreg Roach 115c0112ce8SGreg Roach if ($individual instanceof Individual && $individual->canShow()) { 116c0112ce8SGreg Roach $content .= '<a href="' . e($individual->url()) . '">' . e($user->realName()) . '</a>'; 117c0112ce8SGreg Roach } else { 118c0112ce8SGreg Roach $content .= e($user->realName()); 119c0112ce8SGreg Roach } 120c0112ce8SGreg Roach 121c0112ce8SGreg Roach $content .= ' - ' . e($user->userName()); 122c0112ce8SGreg Roach 123*7c4add84SGreg Roach if (($user->getPreference(User::PREF_CONTACT_METHOD) !== 'none') && (Auth::id() !== $user->id())) { 1248add1155SRico Sonntag if ($type === 'list') { 1258add1155SRico Sonntag $content .= '<br>'; 1268add1155SRico Sonntag } 127e381f98dSGreg 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>'; 1288add1155SRico Sonntag } 1298add1155SRico Sonntag 1308add1155SRico Sonntag if ($type === 'list') { 1318add1155SRico Sonntag $content .= '</li>'; 1328add1155SRico Sonntag } 1338add1155SRico Sonntag } 1348add1155SRico Sonntag } 1358add1155SRico Sonntag 1368add1155SRico Sonntag if ($type === 'list') { 1378add1155SRico Sonntag $content .= '</ul>'; 1388add1155SRico Sonntag } 1398add1155SRico Sonntag 1408add1155SRico Sonntag return $content; 1418add1155SRico Sonntag } 1428add1155SRico Sonntag 1438add1155SRico Sonntag /** 1448add1155SRico Sonntag * @inheritDoc 1458add1155SRico Sonntag */ 1468add1155SRico Sonntag public function usersLoggedIn(): string 1478add1155SRico Sonntag { 148c0112ce8SGreg Roach return $this->usersLoggedInQuery('nolist'); 1498add1155SRico Sonntag } 1508add1155SRico Sonntag 1518add1155SRico Sonntag /** 1528add1155SRico Sonntag * @inheritDoc 1538add1155SRico Sonntag */ 1548add1155SRico Sonntag public function usersLoggedInList(): string 1558add1155SRico Sonntag { 1568add1155SRico Sonntag return $this->usersLoggedInQuery('list'); 1578add1155SRico Sonntag } 1588add1155SRico Sonntag 1598add1155SRico Sonntag /** 1608add1155SRico Sonntag * Returns true if the given user is visible to others. 1618add1155SRico Sonntag * 162e5a6b4d4SGreg Roach * @param UserInterface $user 1638add1155SRico Sonntag * 1648add1155SRico Sonntag * @return bool 1658add1155SRico Sonntag */ 166e5a6b4d4SGreg Roach private function isUserVisible(UserInterface $user): bool 1678add1155SRico Sonntag { 168*7c4add84SGreg Roach return Auth::isAdmin() || $user->getPreference(User::PREF_IS_VISIBLE_ONLINE) === '1'; 1698add1155SRico Sonntag } 1708add1155SRico Sonntag 1718add1155SRico Sonntag /** 1728add1155SRico Sonntag * @inheritDoc 1738add1155SRico Sonntag */ 1748add1155SRico Sonntag public function usersLoggedInTotal(): int 1758add1155SRico Sonntag { 1766ccdf4f0SGreg Roach return count($this->user_service->allLoggedIn()); 1778add1155SRico Sonntag } 1788add1155SRico Sonntag 1798add1155SRico Sonntag /** 1808add1155SRico Sonntag * @inheritDoc 1818add1155SRico Sonntag */ 1828add1155SRico Sonntag public function usersLoggedInTotalAnon(): int 1838add1155SRico Sonntag { 1848add1155SRico Sonntag $anonymous = 0; 1858add1155SRico Sonntag 186e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 1878add1155SRico Sonntag if (!$this->isUserVisible($user)) { 1888add1155SRico Sonntag ++$anonymous; 1898add1155SRico Sonntag } 1908add1155SRico Sonntag } 1918add1155SRico Sonntag 1928add1155SRico Sonntag return $anonymous; 1938add1155SRico Sonntag } 1948add1155SRico Sonntag 1958add1155SRico Sonntag /** 1968add1155SRico Sonntag * @inheritDoc 1978add1155SRico Sonntag */ 1988add1155SRico Sonntag public function usersLoggedInTotalVisible(): int 1998add1155SRico Sonntag { 2008add1155SRico Sonntag $visible = 0; 2018add1155SRico Sonntag 202e5a6b4d4SGreg Roach foreach ($this->user_service->allLoggedIn() as $user) { 2038add1155SRico Sonntag if ($this->isUserVisible($user)) { 2048add1155SRico Sonntag ++$visible; 2058add1155SRico Sonntag } 2068add1155SRico Sonntag } 2078add1155SRico Sonntag 2088add1155SRico Sonntag return $visible; 2098add1155SRico Sonntag } 2108add1155SRico Sonntag 2118add1155SRico Sonntag /** 2128add1155SRico Sonntag * @inheritDoc 2138add1155SRico Sonntag */ 2148add1155SRico Sonntag public function userId(): string 2158add1155SRico Sonntag { 2168add1155SRico Sonntag return (string) Auth::id(); 2178add1155SRico Sonntag } 2188add1155SRico Sonntag 2198add1155SRico Sonntag /** 2208add1155SRico Sonntag * @inheritDoc 2218add1155SRico Sonntag */ 2228add1155SRico Sonntag public function userName(string $visitor_text = ''): string 2238add1155SRico Sonntag { 2248add1155SRico Sonntag if (Auth::check()) { 225e5a6b4d4SGreg Roach return e(Auth::user()->userName()); 2268add1155SRico Sonntag } 2278add1155SRico Sonntag 2288add1155SRico Sonntag // if #username:visitor# was specified, then "visitor" will be returned when the user is not logged in 2298add1155SRico Sonntag return e($visitor_text); 2308add1155SRico Sonntag } 2318add1155SRico Sonntag 2328add1155SRico Sonntag /** 2338add1155SRico Sonntag * @inheritDoc 2348add1155SRico Sonntag */ 2358add1155SRico Sonntag public function userFullName(): string 2368add1155SRico Sonntag { 237e5a6b4d4SGreg Roach return Auth::check() ? '<span dir="auto">' . e(Auth::user()->realName()) . '</span>' : ''; 2388add1155SRico Sonntag } 2398add1155SRico Sonntag 2408add1155SRico Sonntag /** 2418add1155SRico Sonntag * Returns the user count. 2428add1155SRico Sonntag * 2438add1155SRico Sonntag * @return int 2448add1155SRico Sonntag */ 2458add1155SRico Sonntag private function getUserCount(): int 2468add1155SRico Sonntag { 2476ccdf4f0SGreg Roach return count($this->user_service->all()); 2488add1155SRico Sonntag } 2498add1155SRico Sonntag 2508add1155SRico Sonntag /** 2518add1155SRico Sonntag * Returns the administrator count. 2528add1155SRico Sonntag * 2538add1155SRico Sonntag * @return int 2548add1155SRico Sonntag */ 2558add1155SRico Sonntag private function getAdminCount(): int 2568add1155SRico Sonntag { 2576ccdf4f0SGreg Roach return count($this->user_service->administrators()); 2588add1155SRico Sonntag } 2598add1155SRico Sonntag 2608add1155SRico Sonntag /** 2618add1155SRico Sonntag * @inheritDoc 2628add1155SRico Sonntag */ 2638add1155SRico Sonntag public function totalUsers(): string 2648add1155SRico Sonntag { 2658add1155SRico Sonntag return I18N::number($this->getUserCount()); 2668add1155SRico Sonntag } 2678add1155SRico Sonntag 2688add1155SRico Sonntag /** 2698add1155SRico Sonntag * @inheritDoc 2708add1155SRico Sonntag */ 2718add1155SRico Sonntag public function totalAdmins(): string 2728add1155SRico Sonntag { 2738add1155SRico Sonntag return I18N::number($this->getAdminCount()); 2748add1155SRico Sonntag } 2758add1155SRico Sonntag 2768add1155SRico Sonntag /** 2778add1155SRico Sonntag * @inheritDoc 2788add1155SRico Sonntag */ 2798add1155SRico Sonntag public function totalNonAdmins(): string 2808add1155SRico Sonntag { 2818add1155SRico Sonntag return I18N::number($this->getUserCount() - $this->getAdminCount()); 2828add1155SRico Sonntag } 2838add1155SRico Sonntag} 284