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