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