diff options
| author | Greg Roach <fisharebest@gmail.com> | 2015-03-22 18:18:46 +0000 |
|---|---|---|
| committer | Greg Roach <fisharebest@gmail.com> | 2015-03-22 18:18:46 +0000 |
| commit | 405c5ff8ebe2c47f8d58229ec82f6c7266da9b99 (patch) | |
| tree | cfdfecadb38cc337b38a6643cbc547a0fa8620a5 | |
| parent | 58d601976e7117a55e65a6531547a566cc40e83d (diff) | |
| download | webtrees-405c5ff8ebe2c47f8d58229ec82f6c7266da9b99.tar.gz webtrees-405c5ff8ebe2c47f8d58229ec82f6c7266da9b99.tar.bz2 webtrees-405c5ff8ebe2c47f8d58229ec82f6c7266da9b99.zip | |
Fix #502 - change-blocks link and hit counter
| -rw-r--r-- | app/HitCounter.php | 95 | ||||
| -rw-r--r-- | app/Module/ExtraInformationModule.php | 6 | ||||
| -rw-r--r-- | app/Stats.php | 6 | ||||
| -rw-r--r-- | app/Theme/BaseTheme.php | 69 | ||||
| -rw-r--r-- | includes/hitcount.php | 91 | ||||
| -rw-r--r-- | includes/session.php | 7 | ||||
| -rw-r--r-- | index.php | 15 | ||||
| -rw-r--r-- | themes/clouds/css-1.7.0/style.css | 21 | ||||
| -rw-r--r-- | themes/colors/css-1.7.0/style.css | 21 | ||||
| -rw-r--r-- | themes/fab/css-1.7.0/style.css | 21 | ||||
| -rw-r--r-- | themes/minimal/css-1.7.0/style.css | 23 | ||||
| -rw-r--r-- | themes/webtrees/css-1.7.0/style.css | 21 | ||||
| -rw-r--r-- | themes/xenea/css-1.7.0/style.css | 21 |
13 files changed, 185 insertions, 232 deletions
diff --git a/app/HitCounter.php b/app/HitCounter.php new file mode 100644 index 0000000000..6e5dff03fa --- /dev/null +++ b/app/HitCounter.php @@ -0,0 +1,95 @@ +<?php +namespace Fisharebest\Webtrees; + +/** + * webtrees: online genealogy + * Copyright (C) 2015 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class HitCounter - measure page popularity + */ +class HitCounter { + /** + * Count the number of times this page has been viewed. + * + * @param Tree $tree + * @param string $page + * @param string $parameter + * + * @return integer + */ + public static function countHit(Tree $tree, $page, $parameter) { + global $WT_SESSION; + + // Don't increment the counter while we stay on the same page. + if ( + $WT_SESSION->last_tree_id === $tree->getTreeId() && + $WT_SESSION->last_page === $page && + $WT_SESSION->last_parameter === $parameter + ) { + return $WT_SESSION->last_count; + } + + $page_count = self::getCount($tree, $page, $parameter); + + if ($page_count === 0) { + Database::prepare( + "INSERT INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count)" . + " VALUES (:tree_id, :page, :parameter, 1)" + )->execute(array( + 'tree_id' => $tree->getTreeId(), + 'page' => $page, + 'parameter' => $parameter, + )); + } else { + Database::prepare( + "UPDATE `##hit_counter` SET page_count = page_count + 1" . + " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" + )->execute(array( + 'tree_id' => $tree->getTreeId(), + 'page' => $page, + 'parameter' => $parameter, + )); + } + + $page_count++; + + $WT_SESSION->last_tree_id = $tree->getTreeId(); + $WT_SESSION->last_page = $page; + $WT_SESSION->last_parameter = $parameter; + $WT_SESSION->last_count = $page_count; + + return $page_count; + } + + /** + * How many times has a page been viewed + * + * @param Tree $tree + * @param string $page + * @param string $parameter + * + * @return integer + */ + public static function getCount(Tree $tree, $page, $parameter) { + return (int) Database::prepare( + "SELECT page_count FROM `##hit_counter`" . + " WHERE gedcom_id = :tree_id AND page_name = :page AND page_parameter = :parameter" + )->execute(array( + 'tree_id' => $tree->getTreeId(), + 'page' => $page, + 'parameter' => $parameter, + ))->fetchOne(); + } +} diff --git a/app/Module/ExtraInformationModule.php b/app/Module/ExtraInformationModule.php index 70e2d8ebd6..8641aae33f 100644 --- a/app/Module/ExtraInformationModule.php +++ b/app/Module/ExtraInformationModule.php @@ -61,11 +61,7 @@ class ExtraInformationModule extends Module implements ModuleSidebarInterface { print_fact($fact, $controller->record); } } - if ($WT_TREE->getPreference('SHOW_COUNTER')) { - $hitCount = 0; - require WT_ROOT . 'includes/hitcount.php'; - echo '<div id="hitcounter">', I18N::translate('Page views'), ' ', $hitCount, '</div>'; - } + return strip_tags(ob_get_clean(), '<a><div><span>'); } diff --git a/app/Stats.php b/app/Stats.php index cb5ed61cf9..1f2b20ee64 100644 --- a/app/Stats.php +++ b/app/Stats.php @@ -5722,11 +5722,7 @@ class Stats { // indi/fam/sour/etc. } - $count = Database::prepare( - "SELECT SQL_NO_CACHE page_count FROM `##hit_counter`" . - " WHERE gedcom_id=? AND page_name=? AND page_parameter=?" - )->execute(array($this->tree->getTreeId(), $page_name, $page_parameter))->fetchOne(); - return '<span class="hit-counter">' . I18N::number($count) . '</span>'; + return '<span class="odometer">' . I18N::digits(HitCounter::getCount($this->tree, $page_name, $page_parameter)) . '</span>'; } /** diff --git a/app/Theme/BaseTheme.php b/app/Theme/BaseTheme.php index 798cc2d84e..1fca7216af 100644 --- a/app/Theme/BaseTheme.php +++ b/app/Theme/BaseTheme.php @@ -31,6 +31,9 @@ abstract class BaseTheme { /** @var string An escaped version of the "ged=XXX" URL parameter */ protected $tree_url; + /** @var integer The number of times this page has been shown */ + protected $page_views; + /** * Custom themes should place their initialization code in the function hookAfterInit(), not in * the constructor, as all themes get constructed - whether they are used or not. @@ -366,7 +369,8 @@ abstract class BaseTheme { protected function footerContent() { return $this->formatContactLinks() . - $this->logoPoweredBy(); + $this->logoPoweredBy() . + $this->formatPageViews($this->page_views); } /** @@ -401,6 +405,25 @@ abstract class BaseTheme { } /** + * Add markup to the hit counter. + * + * @param integer $count + * + * @return string + */ + protected function formatPageViews($count) { + if ($count > 0) { + return + '<div class="page-views">' . + I18N::plural('This page has been viewed %s time.', 'This page has been viewed %s times.', $count, + '<span class="odometer">' . I18N::digits($count) . '</span>') . + '</div>'; + } else { + return ''; + } + } + + /** * Create a pending changes link for the page footer. * * @return string @@ -486,6 +509,9 @@ abstract class BaseTheme { * @return string */ public function head(PageController $controller) { + // Record this now. By the time we render the footer, $controller no longer exists. + $this->page_views = $this->pageViews($controller); + return '<head>' . $this->headContents($controller) . @@ -988,6 +1014,21 @@ abstract class BaseTheme { } /** + * Generate a menu item to change the blocks on the current (index.php) page. + * + * @return Menu|null + */ + protected function menuChangeBlocks() { + if (WT_SCRIPT_NAME === 'index.php' && Auth::check() && Filter::get('ctype', 'gedcom|user', 'user') === 'user') { + return new Menu(I18N::translate('Customize this page'), 'index_edit.php?user_id=' . Auth::id(), 'menu-change-blocks'); + } elseif (WT_SCRIPT_NAME === 'index.php' && Auth::isManager($this->tree)) { + return new Menu(I18N::translate('Customize this page'), 'index_edit.php?gedcom_id=' . Auth::id(), 'menu-change-blocks'); + } else { + return null; + } + } + + /** * Generate a menu for each of the different charts. * * @param Individual $individual @@ -1534,6 +1575,7 @@ abstract class BaseTheme { $this->menuMyIndividualRecord(), $this->menuMyPedigree(), $this->menuMyAccount(), + $this->menuChangeBlocks(), $this->menuControlPanel(), ))); } else { @@ -1743,6 +1785,31 @@ abstract class BaseTheme { } /** + * How many times has the current page been shown? + * + * @param PageController $controller + * + * @return integer Number of views, or zero for pages that aren't logged. + */ + protected function pageViews(PageController $controller) { + if ($this->tree->getPreference('SHOW_COUNTER')) { + if (isset($controller->record) && $controller->record instanceof GedcomRecord) { + return HitCounter::countHit($this->tree, WT_SCRIPT_NAME, $controller->record->getXref()); + } elseif (isset($controller->root) && $controller->root instanceof GedcomRecord) { + return HitCounter::countHit($this->tree, WT_SCRIPT_NAME, $controller->root->getXref()); + } elseif (WT_SCRIPT_NAME === 'index.php') { + if (Auth::check() && Filter::get('ctype') !== 'gedcom') { + return HitCounter::countHit($this->tree, WT_SCRIPT_NAME, 'user:' . Auth::id()); + } else { + return HitCounter::countHit($this->tree, WT_SCRIPT_NAME, 'gedcom:' . $this->tree->getTreeId()); + } + } + } + + return 0; + } + + /** * Misecellaneous dimensions, fonts, styles, etc. * * @param string $parameter_name diff --git a/includes/hitcount.php b/includes/hitcount.php deleted file mode 100644 index d2be22318e..0000000000 --- a/includes/hitcount.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php -namespace Fisharebest\Webtrees; - -/** - * webtrees: online genealogy - * Copyright (C) 2015 webtrees development team - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/** - * Defined in session.php - * - * @global Tree $WT_TREE - */ -global $WT_TREE; - -// Only record hits for certain pages -switch (WT_SCRIPT_NAME) { -case 'index.php': - switch (Filter::get('ctype', 'gedcom|user', Auth::check() ? 'user' : 'gedcom')) { - case 'user': - $page_parameter = 'user:' . Auth::check(); - break; - case 'gedcom': - $page_parameter = 'gedcom:' . $WT_TREE->getTreeId(); - break; - default: - $page_parameter = ''; - break; - } - break; -case 'individual.php': - $page_parameter = Filter::get('pid', WT_REGEX_XREF); - break; -case 'family.php': - $page_parameter = Filter::get('famid', WT_REGEX_XREF); - break; -case 'source.php': - $page_parameter = Filter::get('sid', WT_REGEX_XREF); - break; -case 'repo.php': - $page_parameter = Filter::get('rid', WT_REGEX_XREF); - break; -case 'note.php': - $page_parameter = Filter::get('nid', WT_REGEX_XREF); - break; -case 'mediaviewer.php': - $page_parameter = Filter::get('mid', WT_REGEX_XREF); - break; -default: - $page_parameter = ''; - break; -} -if ($page_parameter) { - $hitCount = Database::prepare( - "SELECT page_count FROM `##hit_counter`" . - " WHERE gedcom_id=? AND page_name=? AND page_parameter=?" - )->execute(array($WT_TREE->getTreeId(), WT_SCRIPT_NAME, $page_parameter))->fetchOne(); - - // Only record one hit per session - if ($page_parameter && empty($WT_SESSION->SESSION_PAGE_HITS[WT_SCRIPT_NAME . $page_parameter])) { - $WT_SESSION->SESSION_PAGE_HITS[WT_SCRIPT_NAME . $page_parameter] = true; - if (is_null($hitCount)) { - $hitCount = 1; - Database::prepare( - "INSERT INTO `##hit_counter` (gedcom_id, page_name, page_parameter, page_count) VALUES (?, ?, ?, ?)" - )->execute(array($WT_TREE->getTreeId(), WT_SCRIPT_NAME, $page_parameter, $hitCount)); - } else { - $hitCount++; - Database::prepare( - "UPDATE `##hit_counter` SET page_count=?" . - " WHERE gedcom_id=? AND page_name=? AND page_parameter=?" - )->execute(array($hitCount, $WT_TREE->getTreeId(), WT_SCRIPT_NAME, $page_parameter)); - } - } -} else { - $hitCount = 1; -} - -$hitCount = '<span class="hit-counter">' . I18N::number($hitCount) . '</span>'; - -unset($page_name, $page_parameter); diff --git a/includes/session.php b/includes/session.php index f0e20baab5..0d1d8024e6 100644 --- a/includes/session.php +++ b/includes/session.php @@ -543,13 +543,6 @@ if (substr(WT_SCRIPT_NAME, 0, 5) === 'admin' || WT_SCRIPT_NAME === 'module.php' $WT_SESSION->theme_id = $theme_id; } -// Page hit counter - load after theme, as we need theme formatting -if ($WT_TREE && $WT_TREE->getPreference('SHOW_COUNTER') && !Auth::isSearchEngine()) { - require WT_ROOT . 'includes/hitcount.php'; -} else { - $hitCount = ''; -} - // Search engines are only allowed to see certain pages. if (Auth::isSearchEngine() && !in_array(WT_SCRIPT_NAME, array( 'index.php', 'indilist.php', 'module.php', 'mediafirewall.php', @@ -131,17 +131,4 @@ if ($blocks['side']) { } echo '</div>'; } - -echo '<div id="link_change_blocks">'; - -if ($ctype === 'user') { - echo '<a href="index_edit.php?user_id=' . Auth::id() . '">', I18N::translate('Change the blocks on this page'), '</a>'; -} elseif ($ctype === 'gedcom' && Auth::isManager($WT_TREE)) { - echo '<a href="index_edit.php?gedcom_id=' . $WT_TREE->getTreeId() . '">', I18N::translate('Change the blocks on this page'), '</a>'; -} - -if ($WT_TREE->getPreference('SHOW_COUNTER')) { - echo '<span>' . /* I18N: The number of [...] */ I18N::translate('Page views') . ' ' . $hitCount . '</span>'; -} - -echo '</div></div>'; +echo '</div>'; diff --git a/themes/clouds/css-1.7.0/style.css b/themes/clouds/css-1.7.0/style.css index 149c17633d..7f624987ea 100644 --- a/themes/clouds/css-1.7.0/style.css +++ b/themes/clouds/css-1.7.0/style.css @@ -2132,10 +2132,11 @@ dd .deletelink { float: left; } -.hit-counter { +.odometer { + font-family: courier, mono-space; + font-weight: bold; background: #000; color: #fff; - font-weight: bold; } /* ======= General sprite ==== */ @@ -4586,22 +4587,6 @@ footer .error { white-space: nowrap; } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ diff --git a/themes/colors/css-1.7.0/style.css b/themes/colors/css-1.7.0/style.css index 817cb46d90..32c0adcef5 100644 --- a/themes/colors/css-1.7.0/style.css +++ b/themes/colors/css-1.7.0/style.css @@ -2134,10 +2134,11 @@ dd .deletelink { float: left; } -.hit-counter { +.odometer { + font-family: courier, mono-space; + font-weight: bold; background: #000; color: #fff; - font-weight: bold; } /* ======= General sprite ==== */ @@ -4511,22 +4512,6 @@ footer { content: url(images/powered-by-webtrees.png); } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ diff --git a/themes/fab/css-1.7.0/style.css b/themes/fab/css-1.7.0/style.css index 89fd646035..3ca561c630 100644 --- a/themes/fab/css-1.7.0/style.css +++ b/themes/fab/css-1.7.0/style.css @@ -2045,10 +2045,11 @@ dd .deletelink { float: left; } -.hit-counter { +.odometer { + font-family: courier, mono-space; + font-weight: bold; background: #000; color: #fff; - font-weight: bold; } /* ======= General sprite ==== */ @@ -4426,22 +4427,6 @@ footer { content: url(images/powered-by-webtrees.png); } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ diff --git a/themes/minimal/css-1.7.0/style.css b/themes/minimal/css-1.7.0/style.css index e65e917790..5436e619e6 100644 --- a/themes/minimal/css-1.7.0/style.css +++ b/themes/minimal/css-1.7.0/style.css @@ -2050,10 +2050,11 @@ dd .deletelink { float: left; } -.hit-counter { - background: #555; - color: #fff; +.odometer { + font-family: courier, mono-space; font-weight: bold; + background: #000; + color: #fff; } /* ======= General sprite ==== */ @@ -4388,22 +4389,6 @@ footer { margin-top: 10px; } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ diff --git a/themes/webtrees/css-1.7.0/style.css b/themes/webtrees/css-1.7.0/style.css index a161dd324f..714b208042 100644 --- a/themes/webtrees/css-1.7.0/style.css +++ b/themes/webtrees/css-1.7.0/style.css @@ -2038,10 +2038,11 @@ dd .deletelink { float: left; } -.hit-counter { +.odometer { + font-family: courier, mono-space; + font-weight: bold; background: #000; color: #fff; - font-weight: bold; } /* ======= General sprite ==== */ @@ -4429,22 +4430,6 @@ footer { content: url(images/powered-by-webtrees.png); } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ diff --git a/themes/xenea/css-1.7.0/style.css b/themes/xenea/css-1.7.0/style.css index 2701bd213d..51ffaa0fb0 100644 --- a/themes/xenea/css-1.7.0/style.css +++ b/themes/xenea/css-1.7.0/style.css @@ -2049,10 +2049,11 @@ dd .deletelink { float: left; } -.hit-counter { +.odometer { + font-family: courier, mono-space; + font-weight: bold; background: #000; color: #fff; - font-weight: bold; } /* ======= General sprite ==== */ @@ -4441,22 +4442,6 @@ footer { content: url(images/powered-by-webtrees.png); } -#link_change_blocks { - clear: both; - margin: 0 auto; - padding: 25px 0 0; - text-align: center; - width: 400px; -} - -#link_change_blocks span { - padding: 0 50px; -} - -#link_change_blocks span span { - padding: 0 3px; -} - /* ====== End Theme Footer ===== */ /* ====== Theme Icons ========== */ |
