From: Andrew Garrett Date: Wed, 19 Nov 2008 12:01:43 +0000 (+0000) Subject: Starter for a re-jig of hit counting (in a per-day table). X-Git-Tag: 1.31.0-rc.0~44263 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=1c2f4514f80ec6e775c57c7e401ccb9925b8d94e;p=lhc%2Fweb%2Fwiklou.git Starter for a re-jig of hit counting (in a per-day table). Needs configurability, purty graphs, and some cleanup in the back-end. --- diff --git a/includes/Article.php b/includes/Article.php index f64e9f413c..662ab21245 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -3125,9 +3125,11 @@ class Article { $acchitsTable = $dbw->tableName( 'acchits' ); if( $wgHitcounterUpdateFreq <= 1 ) { - $dbw->query( "UPDATE $pageTable SET page_counter = page_counter + 1 WHERE page_id = $id" ); + self::incrementCounterByValue( $id, 1 ); return; } + + ## TODO: Will get to making this stuff use the new infrastructure. # Not important enough to warrant an error page in case of failure $oldignore = $dbw->ignoreErrors( true ); @@ -3171,6 +3173,47 @@ class Article { } $dbw->ignoreErrors( $oldignore ); } + + static function incrementCounterByValue( $article_id, $number ) { + $dbw = wfGetDB( DB_MASTER ); + $dbr = wfGetDB( DB_SLAVE ); + $oldIgnore = $dbw->ignoreErrors( true ); + + ## Does a row already exist? + ## We really need ON DUPLICATE KEY UPDATE :( + $startOfToday = $dbw->timestamp( strtotime( '0:00' ) ); // Hack hack hack + $endOfToday = $dbw->timestamp( strtotime( '0:00 tomorrow' ) ); + $rowExists = $dbr->selectField( 'hit_statistics', '1', array( 'hs_page' => $article_id, "hs_period_start='$startOfToday'", "hs_period_end='$endOfToday'" ), __METHOD__ ); + + if ($rowExists) { + $dbw->update( 'hit_statistics', array( 'hs_count=hs_count+'.intval($number) ), array( 'hs_page' => $article_id, 'hs_period_start' => $startOfToday, 'hs_period_end' => $endOfToday ), __METHOD__ ); + } else { + $row = array( + 'hs_page' => $article_id, + 'hs_period_start' => $startOfToday, + 'hs_period_end' => $endOfToday, + 'hs_period_length' => 86400, // One day. + 'hs_count' => $number + ); + + $dbw->insert( 'hit_statistics', $row, __METHOD__ ); + + ## Update with the previous day's hits... + Article::updatePageRowCounter( $article_id ); + } + + $dbw->ignoreErrors( false ); + } + + static function updatePageRowCounter( $article_id ) { + $dbw = wfGetDB( DB_MASTER ); + $oi = $dbw->ignoreErrors( true ); + + $total = $dbw->selectField( 'hit_statistics', 'sum(hs_count)', array( 'hs_page' => $article_id ), __METHOD__ ); + $dbw->update( 'page', array( 'page_counter' => $total ), array( 'page_id' => $article_id ), __METHOD__ ); + + $dbw->ignoreErrors( $oi ); + } /**#@+ * The onArticle*() functions are supposed to be a kind of hooks diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index b531599c24..1e75ca0c22 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -471,6 +471,7 @@ $wgAutoloadLocalClasses = array( 'PageArchive' => 'includes/specials/SpecialUndelete.php', 'PasswordResetForm' => 'includes/specials/SpecialResetpass.php', 'PopularPagesPage' => 'includes/specials/SpecialPopularpages.php', + 'SpecialPageStatistics' => 'includes/specials/SpecialPageStatistics.php', 'PreferencesForm' => 'includes/specials/SpecialPreferences.php', 'RandomPage' => 'includes/specials/SpecialRandompage.php', 'RevisionDeleteForm' => 'includes/specials/SpecialRevisiondelete.php', diff --git a/includes/QueryPage.php b/includes/QueryPage.php index 5f1acdb955..51226ed7b1 100644 --- a/includes/QueryPage.php +++ b/includes/QueryPage.php @@ -49,6 +49,7 @@ $wgQueryPages = array( ); wfRunHooks( 'wgQueryPages', array( &$wgQueryPages ) ); +## Maybe this can be re-enabled with the new hit-counting infrastructure?? global $wgDisableCounters; if ( !$wgDisableCounters ) $wgQueryPages[] = array( 'PopularPagesPage', 'Popularpages' ); diff --git a/includes/Skin.php b/includes/Skin.php index 1da33ec2f6..64f9a22939 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -1269,11 +1269,10 @@ END; if ( 0 == $wgArticle->getID() ) { return ''; } $s = ''; - if ( !$wgDisableCounters ) { - $count = $wgLang->formatNum( $wgArticle->getCount() ); - if ( $count ) { - $s = wfMsgExt( 'viewcount', array( 'parseinline' ), $count ); - } + $count = $wgArticle->getCount(); + if ( $count ) { + $count = $wgLang->formatNum( $count ); + $s = wfMsgExt( 'viewcount', array( 'parseinline' ), $count ); } if( $wgMaxCredits != 0 ){ diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php index 33307e3133..4e15515f1f 100644 --- a/includes/SkinTemplate.php +++ b/includes/SkinTemplate.php @@ -138,7 +138,7 @@ class SkinTemplate extends Skin { global $wgScript, $wgStylePath, $wgContLanguageCode; global $wgMimeType, $wgJsMimeType, $wgOutputEncoding, $wgRequest; global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces; - global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks; + global $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks; global $wgMaxCredits, $wgShowCreditsIfMax; global $wgPageShowWatchingUsers; global $wgUseTrackbacks, $wgUseSiteJs; @@ -329,8 +329,10 @@ class SkinTemplate extends Skin { if ( $out->isArticle() and (!isset( $oldid ) or isset( $diff )) and $wgArticle and 0 != $wgArticle->getID() ) { - if ( !$wgDisableCounters ) { - $viewcount = $wgLang->formatNum( $wgArticle->getCount() ); + $count = $wgArticle->getCount(); + + if ( $count ) { + $viewcount = $wgLang->formatNum( $count ); if ( $viewcount ) { $tpl->set('viewcount', wfMsgExt( 'viewcount', array( 'parseinline' ), $viewcount ) ); } else { diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index a6afba45c0..9d1d503d1a 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -158,6 +158,7 @@ class SpecialPage 'Randomredirect' => 'SpecialRandomredirect', 'Withoutinterwiki' => array( 'SpecialPage', 'Withoutinterwiki' ), 'Filepath' => array( 'SpecialPage', 'Filepath' ), + 'PageStatistics' => 'SpecialPageStatistics', 'Mypage' => array( 'SpecialMypage' ), 'Mytalk' => array( 'SpecialMytalk' ), diff --git a/includes/specials/SpecialPageStatistics.php b/includes/specials/SpecialPageStatistics.php new file mode 100644 index 0000000000..3781c7345c --- /dev/null +++ b/includes/specials/SpecialPageStatistics.php @@ -0,0 +1,125 @@ +setPageTitle( wfMsg( 'pagestatistics' ) ); + $wgOut->setRobotPolicy( "noindex,nofollow" ); + $wgOut->setArticleRelated( false ); + $wgOut->enableClientCache( false ); + + $this->setHeaders(); + $this->loadParameters( $subpage ); + + if ($this->page) { + $this->showStatistics( ); + } else { + $this->showMain(); + } + + + } + + function loadParameters( $subpage ) { + global $wgRequest; + + $this->page = $subpage; + $this->periodStart = $wgRequest->getVal( 'periodstart' ); + $this->periodEnd = $wgRequest->getVal( 'periodend' ); + + if ($p = $wgRequest->getVal( 'target' ) ) + $this->page = $p; + } + + function showSearchBox( ) { + global $wgOut; + + $fields = array(); + $fields['pagestatistics-page'] = Xml::input( 'target', 45, $this->page ); + $fields['pagestatistics-periodstart'] = Xml::input( 'periodstart', 45, $this->periodStart ); + $fields['pagestatistics-periodend'] = Xml::input( 'periodend', 45, $this->periodEnd ); + + $form = Xml::buildForm( $fields, 'pagestatistics-search' ); + $form .= Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ); + $form = Xml::tags( 'form', array( 'method' => 'GET', 'action' => $this->getTitle()->getFullURL() ), $form ); + $form = Xml::fieldset( wfMsgExt( 'pagestatistics-search-legend', 'parseinline' ), $form ); + + $wgOut->addHTML( $form ); + } + + function showMain() { + global $wgUser, $wgOut; + + $sk = $wgUser->getSkin(); + + ## Create initial intro + $wgOut->addWikiMsg( 'pagestatistics-intro' ); + + ## Fieldset with search stuff + $this->showSearchBox( ); + } + + function showStatistics() { + global $wgLang, $wgOut; + + $this->showSearchBox(); + + ## For now, just a data table. + $dbr = wfGetDB( DB_SLAVE ); + + $article = new Article( Title::newFromText( $this->page ) ); + + $periodStart = $dbr->addQuotes( $dbr->timestamp( strtotime( $this->periodStart ) ) ); + $periodEnd = $dbr->addQuotes( $dbr->timestamp( strtotime( $this->periodEnd ) ) ); + + $res = $dbr->select( 'hit_statistics', '*', array( "hs_period_start>=$periodStart", "hs_period_end<=$periodEnd", 'hs_page' => $article->getId() ), __METHOD__ ); + + $html = Xml::tags( 'th', null, wfMsgExt( 'pagestatistics-datatable-periodstart', 'parseinline' ) ); + $html .= Xml::tags( 'th', null, wfMsgExt( 'pagestatistics-datatable-periodend', 'parseinline' ) ); + $html .= Xml::tags( 'th', null, wfMsgExt( 'pagestatistics-datatable-count', 'parseinline' ) ); + $html = Xml::tags( 'tr', null, $html ); + + $total = 0; + $data = array(); + while( $row = $dbr->fetchObject( $res ) ) { + $thisData = array( + 'count' => $row->hs_count, + 'start' => $row->hs_period_start, + 'end' => $row->hs_period_end, + ); + $data[] = $thisData; + + $total += $row->hs_count; + + $thisRow = Xml::tags( 'td', null, $wgLang->timeanddate( $row->hs_period_start ) ); + $thisRow .= Xml::tags('td', null, $wgLang->timeanddate( $row->hs_period_end ) ); + $thisRow .= Xml::tags('td', null, $row->hs_count ); + $thisRow = Xml::tags( 'tr', null, $thisRow ); + + $html .= "$thisRow\n"; + } + + ## Rollup total row + $totalLabel = Xml::tags( 'strong', null, wfMsgExt( 'pagestatistics-datatable-total', 'parseinline' ) ); + $thisRow = Xml::tags( 'td', null, $totalLabel ); + $thisRow .= Xml::tags('td', null, $totalLabel ); + $thisRow .= Xml::tags('td', null, $total ); + $thisRow = Xml::tags( 'tr', null, $thisRow ); + + $html .= "$thisRow\n"; + + $html = Xml::tags( 'table', null, Xml::tags( 'tbody', null, $html ) ); + $wgOut->addHTML( $html ); + + $wgOut->addWikitext( 'Purty graph goes here' ); + + ## TODO purty graph :) + } +} \ No newline at end of file diff --git a/includes/specials/SpecialStatistics.php b/includes/specials/SpecialStatistics.php index cd4a9b2b84..cc2af0719b 100644 --- a/includes/specials/SpecialStatistics.php +++ b/includes/specials/SpecialStatistics.php @@ -31,6 +31,7 @@ function wfSpecialStatistics( $par = '' ) { $numJobs = SiteStats::jobs(); # Staticic - views + ## Maybe re-enablable with new hitcounter infrastructure, plus more goodies like newly popular pages. $viewsStats = ''; if( !$wgDisableCounters ) { $viewsStats = Xml::tags( 'th', array( 'colspan' => '2' ), wfMsg( 'statistics-header-views' ) ) . diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index ca1907b4fb..f2afaaa019 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -3727,6 +3727,19 @@ Enter the filename without the "{{ns:image}}:" prefix.', 'fileduplicatesearch-result-1' => 'The file "$1" has no identical duplication.', 'fileduplicatesearch-result-n' => 'The file "$1" has {{PLURAL:$2|1 identical duplication|$2 identical duplications}}.', +## Special:PageStatistics +'pagestatistics' => 'Page statistics', +'pagestatistics-intro' => 'This page allows you to search page-view statistics for given pages on the wiki.', +'pagestatistics-search-legend' => 'Search for statistics', +'pagestatistics-page' => 'Page:', +'pagestatistics-periodstart' => 'Start of period:', +'pagestatistics-periodend' => 'End of period:', +'pagestatistics-search' => 'Search', +'pagestatistics-datatable-periodstart' => 'Start of period', +'pagestatistics-datatable-periodend' => 'End of period', +'pagestatistics-datatable-count' => 'Count', +'pagestatistics-datatable-total' => 'Total', + # Special:SpecialPages 'specialpages' => 'Special pages', 'specialpages-summary' => '', # do not translate or duplicate this message to other languages diff --git a/maintenance/archives/patch-hit_statistics.sql b/maintenance/archives/patch-hit_statistics.sql new file mode 100644 index 0000000000..96053c4b73 --- /dev/null +++ b/maintenance/archives/patch-hit_statistics.sql @@ -0,0 +1,14 @@ +-- Creates the hit_statistics table, for storing, as the name implies, hit statistics. + +CREATE TABLE /*$wgDBprefix*/hit_statistics ( + hs_page bigint(20) NOT NULL, -- Maybe this should be a namespace/title tuple instead. + hs_period_start binary(14) NOT NULL, + hs_period_end binary(14) NOT NULL, + hs_period_length bigint(20) NOT NULL, + hs_count bigint(20) NOT NULL, + + PRIMARY KEY (hs_page,hs_period_start), + KEY hs_period_start (hs_period_start), + KEY hs_period_length (hs_period_length), + KEY hs_count (hs_count) +) /*$wgDBTableOptions*/; \ No newline at end of file