xref: /webtrees/app/Module/HitCountFooterModule.php (revision 8c67195698d00428c7c321fc6588ad354a2d92e1)
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\Module;
19
20use Fisharebest\Webtrees\I18N;
21use Fisharebest\Webtrees\Session;
22use Fisharebest\Webtrees\Tree;
23use Fisharebest\Webtrees\User;
24use Illuminate\Database\Capsule\Manager as DB;
25use Symfony\Component\HttpFoundation\Request;
26
27/**
28 * Class HitCountFooterModule - show the popular sites in the footer.
29 */
30class HitCountFooterModule extends AbstractModule implements ModuleFooterInterface
31{
32    use ModuleFooterTrait;
33
34    // Which pages/routes do we count?
35    // For historical reasons, we record the names of the original webtrees script and parameter.
36    protected const PAGE_NAMES = [
37        'family'     => 'family.php',
38        'individual' => 'individual.php',
39        'media'      => 'mediaviewer.php',
40        'note'       => 'note.php',
41        'repository' => 'repo.php',
42        'source'     => 'source.php',
43        'tree-page'  => 'index.php',
44        'user-page'  => 'index.php',
45    ];
46
47    /** @var Request */
48    protected $request;
49
50    /** @var Tree|null */
51    protected $tree;
52
53    /** @var User */
54    protected $user;
55
56    /** @var int */
57    protected $page_hits = 0;
58
59    /**
60     * How should this module be labelled on tabs, footers, etc.?
61     *
62     * @return string
63     */
64    public function title(): string
65    {
66        /* I18N: Name of a module */
67        return I18N::translate('Hit counters');
68    }
69
70    /**
71     * A sentence describing what this module does.
72     *
73     * @return string
74     */
75    public function description(): string
76    {
77        /* I18N: Description of the “Hit counters” module */
78        return I18N::translate('Count the visits to each page');
79    }
80
81    /**
82     * Dependency injection.
83     *
84     * @param Tree|null $tree
85     * @param User      $user
86     * @param Request   $request
87     */
88    public function boot(?Tree $tree, User $user, Request $request): void
89    {
90        $this->tree    = $tree;
91        $this->user    = $user;
92        $this->request = $request;
93
94        if ($this->tree !== null && $this->tree->getPreference('SHOW_COUNTER')) {
95            $route = $request->get('route');
96
97            $page_name = self::PAGE_NAMES[$route] ?? '';
98
99            switch ($route) {
100                case 'family':
101                case 'individual':
102                case 'media':
103                case 'note':
104                case 'repository':
105                case 'source':
106                $this->page_hits = $this->countHit($page_name, $request->get('xref', ''));
107                    break;
108
109                case 'tree-page':
110                    $this->page_hits = $this->countHit($page_name, 'gedcom:' . $this->tree->id());
111                    break;
112
113                case 'user-page':
114                    $this->page_hits = $this->countHit($page_name, 'user:' . $this->user->id());
115                    break;
116            }
117        }
118    }
119
120    /**
121     * The default position for this footer.  It can be changed in the control panel.
122     *
123     * @return int
124     */
125    public function defaultFooterOrder(): int
126    {
127        return 3;
128    }
129
130    /**
131     * A footer, to be added at the bottom of every page.
132     *
133     * @return string
134     */
135    public function getFooter(): string
136    {
137        if ($this->tree === null || $this->page_hits === 0) {
138            return '';
139        }
140
141        $digits = '<span class="odometer">' . I18N::digits($this->page_hits) . '</span>';
142
143        return view('modules/hit-counter/footer', [
144            'hit_counter' => I18N::plural('This page has been viewed %s time.', 'This page has been viewed %s times.', $this->page_hits, $digits),
145        ]);
146    }
147
148    /**
149     * Increment the page count.
150     *
151     * @param string $page
152     * @param string $parameter
153     *
154     * @return int
155     */
156    protected function countHit($page, $parameter): int
157    {
158        $gedcom_id = $this->tree->id();
159
160        // Don't increment the counter while we stay on the same page.
161        if (
162            Session::get('last_gedcom_id') === $gedcom_id &&
163            Session::get('last_page_name') === $page &&
164            Session::get('last_page_parameter') === $parameter
165        ) {
166            return Session::get('last_count');
167        }
168
169        $count = (int) DB::table('hit_counter')
170            ->where('gedcom_id', '=', $this->tree->id())
171            ->where('page_name', '=', $page)
172            ->where('page_parameter', '=', $parameter)
173            ->value('page_count');
174
175        $count++;
176
177        DB::table('hit_counter')->updateOrInsert([
178            'gedcom_id'      => $this->tree->id(),
179            'page_name'      => $page,
180            'page_parameter' => $parameter,
181        ], [
182            'page_count' => $count,
183        ]);
184
185        Session::put('last_gedcom_id', $gedcom_id);
186        Session::put('last_page_name', $page);
187        Session::put('last_page_parameter', $parameter);
188        Session::put('last_count', $count);
189
190        return $count;
191    }
192}
193