133c34396SGreg Roach<?php 233c34396SGreg Roach/** 333c34396SGreg Roach * webtrees: online genealogy 433c34396SGreg Roach * Copyright (C) 2019 webtrees development team 533c34396SGreg Roach * This program is free software: you can redistribute it and/or modify 633c34396SGreg Roach * it under the terms of the GNU General Public License as published by 733c34396SGreg Roach * the Free Software Foundation, either version 3 of the License, or 833c34396SGreg Roach * (at your option) any later version. 933c34396SGreg Roach * This program is distributed in the hope that it will be useful, 1033c34396SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 1133c34396SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1233c34396SGreg Roach * GNU General Public License for more details. 1333c34396SGreg Roach * You should have received a copy of the GNU General Public License 1433c34396SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 1533c34396SGreg Roach */ 1633c34396SGreg Roachdeclare(strict_types=1); 1733c34396SGreg Roach 1833c34396SGreg Roachnamespace Fisharebest\Webtrees\Module; 1933c34396SGreg Roach 20e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 2133c34396SGreg Roachuse Fisharebest\Webtrees\I18N; 2233c34396SGreg Roachuse Fisharebest\Webtrees\Session; 2333c34396SGreg Roachuse Fisharebest\Webtrees\Tree; 2433c34396SGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 256ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface; 266ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 276ccdf4f0SGreg Roachuse Psr\Http\Server\MiddlewareInterface; 286ccdf4f0SGreg Roachuse Psr\Http\Server\RequestHandlerInterface; 2933c34396SGreg Roach 3033c34396SGreg Roach/** 310c8c69d4SGreg Roach * Class HitCountFooterModule - show the number of page hits in the footer. 3233c34396SGreg Roach */ 330c8c69d4SGreg Roachclass HitCountFooterModule extends AbstractModule implements ModuleFooterInterface, MiddlewareInterface 3433c34396SGreg Roach{ 3533c34396SGreg Roach use ModuleFooterTrait; 3633c34396SGreg Roach 3733c34396SGreg Roach // Which pages/routes do we count? 3833c34396SGreg Roach // For historical reasons, we record the names of the original webtrees script and parameter. 3933c34396SGreg Roach protected const PAGE_NAMES = [ 4033c34396SGreg Roach 'family' => 'family.php', 4133c34396SGreg Roach 'individual' => 'individual.php', 4233c34396SGreg Roach 'media' => 'mediaviewer.php', 4333c34396SGreg Roach 'note' => 'note.php', 4433c34396SGreg Roach 'repository' => 'repo.php', 4533c34396SGreg Roach 'source' => 'source.php', 4633c34396SGreg Roach 'tree-page' => 'index.php', 4733c34396SGreg Roach 'user-page' => 'index.php', 4833c34396SGreg Roach ]; 4933c34396SGreg Roach 500c8c69d4SGreg Roach /** @var int Count of visits to the current page */ 5133c34396SGreg Roach protected $page_hits = 0; 5233c34396SGreg Roach 5333c34396SGreg Roach /** 54d4c04956SGreg Roach * How should this module be labelled on tabs, footers, etc.? 55d4c04956SGreg Roach * 56d4c04956SGreg Roach * @return string 57d4c04956SGreg Roach */ 58d4c04956SGreg Roach public function title(): string 59d4c04956SGreg Roach { 60d4c04956SGreg Roach /* I18N: Name of a module */ 61d4c04956SGreg Roach return I18N::translate('Hit counters'); 62d4c04956SGreg Roach } 63d4c04956SGreg Roach 64d4c04956SGreg Roach /** 65d4c04956SGreg Roach * A sentence describing what this module does. 66d4c04956SGreg Roach * 67d4c04956SGreg Roach * @return string 68d4c04956SGreg Roach */ 69d4c04956SGreg Roach public function description(): string 70d4c04956SGreg Roach { 71d4c04956SGreg Roach /* I18N: Description of the “Hit counters” module */ 72d4c04956SGreg Roach return I18N::translate('Count the visits to each page'); 73d4c04956SGreg Roach } 74d4c04956SGreg Roach 75d4c04956SGreg Roach /** 7633c34396SGreg Roach * The default position for this footer. It can be changed in the control panel. 7733c34396SGreg Roach * 7833c34396SGreg Roach * @return int 7933c34396SGreg Roach */ 8033c34396SGreg Roach public function defaultFooterOrder(): int 8133c34396SGreg Roach { 8233c34396SGreg Roach return 3; 8333c34396SGreg Roach } 8433c34396SGreg Roach 8533c34396SGreg Roach /** 8633c34396SGreg Roach * A footer, to be added at the bottom of every page. 8733c34396SGreg Roach * 880c8c69d4SGreg Roach * @param Tree|null $tree 890c8c69d4SGreg Roach * 9033c34396SGreg Roach * @return string 9133c34396SGreg Roach */ 920c8c69d4SGreg Roach public function getFooter(?Tree $tree): string 9333c34396SGreg Roach { 940c8c69d4SGreg Roach if ($this->page_hits === 0) { 9533c34396SGreg Roach return ''; 9633c34396SGreg Roach } 9733c34396SGreg Roach 9833c34396SGreg Roach $digits = '<span class="odometer">' . I18N::digits($this->page_hits) . '</span>'; 9933c34396SGreg Roach 10033c34396SGreg Roach return view('modules/hit-counter/footer', [ 10133c34396SGreg Roach 'hit_counter' => I18N::plural('This page has been viewed %s time.', 'This page has been viewed %s times.', $this->page_hits, $digits), 10233c34396SGreg Roach ]); 10333c34396SGreg Roach } 10433c34396SGreg Roach 10533c34396SGreg Roach /** 1066ccdf4f0SGreg Roach * @param ServerRequestInterface $request 1076ccdf4f0SGreg Roach * @param RequestHandlerInterface $handler 1086ccdf4f0SGreg Roach * 1096ccdf4f0SGreg Roach * @return ResponseInterface 1106ccdf4f0SGreg Roach */ 1116ccdf4f0SGreg Roach public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface 1126ccdf4f0SGreg Roach { 1136ccdf4f0SGreg Roach $tree = app(Tree::class); 1146ccdf4f0SGreg Roach 1156ccdf4f0SGreg Roach if ($tree instanceof Tree && $tree->getPreference('SHOW_COUNTER')) { 116*4f2a4a62SGreg Roach $route = $request->getQueryParams()['route'] ?? ''; 1176ccdf4f0SGreg Roach 1186ccdf4f0SGreg Roach $page_name = self::PAGE_NAMES[$route] ?? ''; 1196ccdf4f0SGreg Roach 1206ccdf4f0SGreg Roach switch ($route) { 1216ccdf4f0SGreg Roach case 'family': 1226ccdf4f0SGreg Roach case 'individual': 1236ccdf4f0SGreg Roach case 'media': 1246ccdf4f0SGreg Roach case 'note': 1256ccdf4f0SGreg Roach case 'repository': 1266ccdf4f0SGreg Roach case 'source': 127*4f2a4a62SGreg Roach $this->page_hits = $this->countHit($tree, $page_name, $request->getQueryParams()['xref'] ?? ''); 1286ccdf4f0SGreg Roach break; 1296ccdf4f0SGreg Roach 1306ccdf4f0SGreg Roach case 'tree-page': 1316ccdf4f0SGreg Roach $this->page_hits = $this->countHit($tree, $page_name, 'gedcom:' . $tree->id()); 1326ccdf4f0SGreg Roach break; 1336ccdf4f0SGreg Roach 1346ccdf4f0SGreg Roach case 'user-page': 1356ccdf4f0SGreg Roach $user = app(UserInterface::class); 1366ccdf4f0SGreg Roach $this->page_hits = $this->countHit($tree, $page_name, 'user:' . $user->id()); 1376ccdf4f0SGreg Roach break; 1386ccdf4f0SGreg Roach } 1396ccdf4f0SGreg Roach } 1406ccdf4f0SGreg Roach 1416ccdf4f0SGreg Roach return $handler->handle($request); 1426ccdf4f0SGreg Roach } 1436ccdf4f0SGreg Roach 1446ccdf4f0SGreg Roach /** 14533c34396SGreg Roach * Increment the page count. 14633c34396SGreg Roach * 1470c8c69d4SGreg Roach * @param Tree $tree 14833c34396SGreg Roach * @param string $page 14933c34396SGreg Roach * @param string $parameter 15033c34396SGreg Roach * 15133c34396SGreg Roach * @return int 15233c34396SGreg Roach */ 1530c8c69d4SGreg Roach protected function countHit(Tree $tree, string $page, string $parameter): int 15433c34396SGreg Roach { 15533c34396SGreg Roach // Don't increment the counter while we stay on the same page. 15633c34396SGreg Roach if ( 1570c8c69d4SGreg Roach Session::get('last_gedcom_id') === $tree->id() && 15833c34396SGreg Roach Session::get('last_page_name') === $page && 15933c34396SGreg Roach Session::get('last_page_parameter') === $parameter 16033c34396SGreg Roach ) { 1610c8c69d4SGreg Roach return (int) Session::get('last_count'); 16233c34396SGreg Roach } 16333c34396SGreg Roach 16433c34396SGreg Roach $count = (int) DB::table('hit_counter') 1650c8c69d4SGreg Roach ->where('gedcom_id', '=', $tree->id()) 16633c34396SGreg Roach ->where('page_name', '=', $page) 16733c34396SGreg Roach ->where('page_parameter', '=', $parameter) 1688491737aSGreg Roach ->value('page_count'); 16933c34396SGreg Roach 17033c34396SGreg Roach $count++; 17133c34396SGreg Roach 17233c34396SGreg Roach DB::table('hit_counter')->updateOrInsert([ 1730c8c69d4SGreg Roach 'gedcom_id' => $tree->id(), 17433c34396SGreg Roach 'page_name' => $page, 17533c34396SGreg Roach 'page_parameter' => $parameter, 17633c34396SGreg Roach ], [ 17733c34396SGreg Roach 'page_count' => $count, 17833c34396SGreg Roach ]); 17933c34396SGreg Roach 1800c8c69d4SGreg Roach Session::put('last_gedcom_id', $tree->id()); 18133c34396SGreg Roach Session::put('last_page_name', $page); 18233c34396SGreg Roach Session::put('last_page_parameter', $parameter); 18333c34396SGreg Roach Session::put('last_count', $count); 18433c34396SGreg Roach 18533c34396SGreg Roach return $count; 18633c34396SGreg Roach } 18733c34396SGreg Roach} 188