xref: /webtrees/app/Module/TopPageViewsModule.php (revision b295534922aa0d15bf8b3821f74784a5ff810d62)
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 */
16namespace Fisharebest\Webtrees\Module;
17
18use Fisharebest\Webtrees\Auth;
19use Fisharebest\Webtrees\Database;
20use Fisharebest\Webtrees\Filter;
21use Fisharebest\Webtrees\GedcomRecord;
22use Fisharebest\Webtrees\I18N;
23use Fisharebest\Webtrees\Tree;
24
25/**
26 * Class TopPageViewsModule
27 */
28class TopPageViewsModule extends AbstractModule implements ModuleBlockInterface {
29	/**
30	 * How should this module be labelled on tabs, menus, etc.?
31	 *
32	 * @return string
33	 */
34	public function getTitle() {
35		return /* I18N: Name of a module */ I18N::translate('Most viewed pages');
36	}
37
38	/**
39	 * A sentence describing what this module does.
40	 *
41	 * @return string
42	 */
43	public function getDescription() {
44		return /* I18N: Description of the “Most visited pages” module */ I18N::translate('A list of the pages that have been viewed the most number of times.');
45	}
46
47	/**
48	 * Generate the HTML content of this block.
49	 *
50	 * @param Tree     $tree
51	 * @param int      $block_id
52	 * @param bool     $template
53	 * @param string[] $cfg
54	 *
55	 * @return string
56	 */
57	public function getBlock(Tree $tree, int $block_id, bool $template = true, array $cfg = []): string {
58		global $ctype;
59
60		$num             = $this->getBlockSetting($block_id, 'num', '10');
61		$count_placement = $this->getBlockSetting($block_id, 'count_placement', 'before');
62
63		extract($cfg, EXTR_OVERWRITE);
64
65		// load the lines from the file
66		$top10 = Database::prepare(
67			"SELECT page_parameter, page_count" .
68			" FROM `##hit_counter`" .
69			" WHERE gedcom_id = :tree_id AND page_name IN ('individual.php','family.php','source.php','repo.php','note.php','mediaviewer.php')" .
70			" ORDER BY page_count DESC LIMIT :limit"
71		)->execute([
72			'tree_id' => $tree->getTreeId(),
73			'limit'   => (int) $num,
74		])->fetchAssoc();
75
76		$content = '<table>';
77		foreach ($top10 as $id => $count) {
78			$record = GedcomRecord::getInstance($id, $tree);
79			if ($record && $record->canShow()) {
80				$content .= '<tr>';
81				if ($count_placement == 'before') {
82					$content .= '<td dir="ltr" style="text-align:right">[' . $count . ']</td>';
83				}
84				$content .= '<td class="name2" ><a href="' . e($record->url()) . '">' . $record->getFullName() . '</a></td>';
85				if ($count_placement == 'after') {
86					$content .= '<td dir="ltr" style="text-align:right">[' . $count . ']</td>';
87				}
88				$content .= '</tr>';
89			}
90		}
91		$content .= '</table>';
92
93		if ($template) {
94			if ($ctype === 'gedcom' && Auth::isManager($tree)) {
95				$config_url = route('tree-page-block-edit', ['block_id' => $block_id, 'ged' => $tree->getName()]);
96			} elseif ($ctype === 'user' && Auth::check()) {
97				$config_url = route('user-page-block-edit', ['block_id' => $block_id, 'ged' => $tree->getName()]);
98			} else {
99				$config_url = '';
100			}
101
102			return view('modules/block-template', [
103				'block'      => str_replace('_', '-', $this->getName()),
104				'id'         => $block_id,
105				'config_url' => $config_url,
106				'title'      => $this->getTitle(),
107				'content'    => $content,
108			]);
109		} else {
110			return $content;
111		}
112	}
113
114	/**
115	 * Should this block load asynchronously using AJAX?
116	 *
117	 * Simple blocks are faster in-line, more comples ones
118	 * can be loaded later.
119	 *
120	 * @return bool
121	 */
122	public function loadAjax(): bool {
123		return true;
124	}
125
126	/**
127	 * Can this block be shown on the user’s home page?
128	 *
129	 * @return bool
130	 */
131	public function isUserBlock(): bool {
132		return false;
133	}
134
135	/**
136	 * Can this block be shown on the tree’s home page?
137	 *
138	 * @return bool
139	 */
140	public function isGedcomBlock(): bool {
141		return true;
142	}
143
144	/**
145	 * An HTML form to edit block settings
146	 *
147	 * @param Tree $tree
148	 * @param int  $block_id
149	 *
150	 * @return void
151	 */
152	public function configureBlock(Tree $tree, int $block_id) {
153		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
154			$this->setBlockSetting($block_id, 'num', Filter::postInteger('num', 1, 10000, 10));
155			$this->setBlockSetting($block_id, 'count_placement', Filter::post('count_placement', 'before|after', 'before'));
156
157			return;
158		}
159
160		$num             = $this->getBlockSetting($block_id, 'num', '10');
161		$count_placement = $this->getBlockSetting($block_id, 'count_placement', 'before');
162
163		$options = [
164			'before' => /* I18N: An option in a list-box */ I18N::translate('before'),
165			'after'  => /* I18N: An option in a list-box */ I18N::translate('after'),
166		];
167
168		echo view('modules/top10_pageviews/config', [
169			'count_placement' => $count_placement,
170			'num'             => $num,
171			'options'         => $options,
172		]);
173	}
174}
175