see also: TRBCounter
Most Visited Pages
version 0.3
This is a script based on MostVisited action by George Petsagourakis. It adds new functionality compared to the original version, but is compatible with it (both versions show exactly the same results).
To use this script you need to install this page hit counter (TRBCounter) add-on first. You could also go with its predecessor, GmBowenCounter, but that is not fully compatible and provides less functions. For more details on the incompatibility see TRBCounter description.
This code is tested on Wikka 1.1.6.4RC1 and unstable 1.1.7.0.
What's new in this version
0.3 (since 0.2)
- Bug fixed: a first owner was displayed instead of current one.
- Public-owned pages and pages owned by nobody are distinguished now.
0.2 (since 0.1)
- It can display when a page was last visited (needs TRBCounter 0.6 or newer). Use showlastvisited="true".
- Bug fixed: pages listed in page_hit_counter_disable_pages directive will no more be displayed -- even if they have a hit count > 0 (this may occur if a page had a counter enabled, scored some visits but was later added to the list of pages ignored by a counter).
- You can limit the listing to pages that have been visited within the last X days. Use for example limitdays="5". Note: it’s enough that a page was visited once within the given number of days, and it will be listed. Currently there’s no way say how many times a page was visited within a given number of days, since this information is not stored by a counter.
- Some other small changes.
0.1 (since the original release by George Petsagourakis)
- Support for hidden pages (GmBowenAdminPageControlTool allows doing that) -- it doesn't display them.
- Doesn't display pages that have hit count = 0.
- It's translatable now (in Wikka 1.1.7.0, but compatibility with older versions is retained).
- It's configurable now: the mostvisited action takes some parameters:
- showhits="15" -- will limit the list to 15 most visited pages (but still doesn't display pages that have hit count = 0). Default: 10.
- showrank="false" -- show/hide the numbers on the side of the list (starting from 1). Default: true.
- showowner="true" -- show/hide the owner of each page beside its name. Default: false.
- showtotal="false" -- show/hide total number of hits. Default: true.
- showcurrent="true" -- show/hide number of hits of current revision. Default: false.
- showheader="false" -- show/hide table headers. Default: true.
- class="abc" -- name of the class, which surrounds the output. It is useful if you want to include a tiny, colorless version of MostVisited on your main page for example. Default: mostvisited_containter.
- Replaced fancy array-mangling in PHP with one complicated SQL query.
- Deprecated HTML removed, it's fully skinable by CSS now.
TODO
- Different ways of sorting (by clicking on headers).
- Possibility to see how many visits did older revisions have (and comparing it to how long they lasted, to get their "normalized" popularity). This could be done by adding a new handler.
- Possibility to show how many visits did a page have within last XX days (would require changing the way hits are counted)
- Additional display mode in which owner has its own column.
- Use advanced HTML4 table properties (?).
Instructions
1. How to set this up
All you need to do is create an action file mostvisited.php in a proper place.For an unstable Wikka 1.1.7.0 this will be actions/mostvisited/mostvisited.php.
For Wikka 1.1.6.3 this will be actions/mostvisited.php.
<?php
/**
* Display a list of most visited pages.
*
* @package Actions
* @name MostVisited
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @filesource
*
* @author {@link mailto:[email protected] George Petsagourakis} (first version)
* @author {@link http://wikkawiki.org/KrzysztofTrybowski Krzysztof Trybowski} (later changes)
* @date 06 Feb 2008
*
* @description This file assumes that you are running the counter.php by GmBowen or TRBCounter on your Wakka
*/
// Default translation entries
if (!defined('MOSTVISITED_HEADING')) define('MOSTVISITED_HEADING', 'Most visited pages');
if (!defined('MV_RANK')) define('MV_RANK', 'Rank');
if (!defined('MV_PAGENAME')) define('MV_PAGENAME', 'Page name');
if (!defined('MV_PAGENAME_WITH_OWNER')) define('MV_PAGENAME_WITH_OWNER', 'Page name (page owner)');
if (!defined('MV_CURRENT_VERSION_HITS')) define('MV_CURRENT_VERSION_HITS', 'Current<br> version hits');
if (!defined('MV_TOTAL_HITS')) define('MV_TOTAL_HITS', 'Total hits');
if (!defined('MV_LAST_VISITED')) define('MV_LAST_VISITED', 'Last visited');
if (!defined('MV_LAST_VISITED_UNKNOWN')) define('MV_LAST_VISITED_UNKNOWN', '(unknown)');
if (!defined('MV_OWNER')) define('MV_OWNER', 'Owner'); //not used yet
if (!defined('MV_NOT_OWNED')) define('MV_NOT_OWNED', 'not owned');
if (!defined('MV_PUBLIC_OWNED')) define('MV_PUBLIC_OWNED', 'public');
// Defaults for options and some checking
$showhits=abs($showhits);
$limitdays=abs($limitdays);
if ($showhits==0) $showhits = 10;
if ($limitdays<1) $limitdays = '';
if (!isset($showrank)) $showrank = true;
if (!isset($showowner)) $showowner = false;
if (!isset($showcurrent)) $showcurrent = false;
if (!isset($showtotal)) $showtotal = true;
if (!isset($showheader)) $showheader = true;
if (!isset($showlastvisited)) $showlastvisited = false;
if (!isset($class)) $class = "mostvisited_container"; else $class = $this->CleanTextNode($class);
// If we should show "last visited" column, then these addictions to a query are necessary
if ($showlastvisited or $limitdays)
{
$last_visited = ", MAX(last_visited) AS last_visited ";
$last_visited2 = ",last_visited";
}
else
{
$last_visited = ""; $last_visited2 = "";
}
// Let's prepare a list of PageNames that should have counter disabled and shouldn't be listed
$disable_pages = explode(',',strtr($this->GetConfigValue('page_hit_counter_disable_pages'), array(" " => "", "'" => "")));
// Using a different variable for list in format expected by MySQL
$qr_disable_pages = array();
foreach ($disable_pages as $i => $v) if (!$v == '') array_push($qr_disable_pages, "'".$disable_pages[$i]."'");
if (count($qr_disable_pages) > 0) $qr_disable_pages = " WHERE tag NOT IN (".implode(", ", $qr_disable_pages).") "; else $qr_disable_pages='';
// Let's prepare a query addiction for limitdays
if ($limitdays) $qr_limit_days = " WHERE last_visited > SUBDATE(now(),".$limitdays.") "; else $qr_limit_days = '';
// Database query
$result = $this->Query("SELECT * FROM (SELECT t1.tag,owner,total_hits,current_hits".$last_visited2." FROM (SELECT * FROM (SELECT tag,SUM(hits) AS total_hits ".$last_visited." FROM ".$this->config['table_prefix']."pages ".$qr_disable_pages." GROUP BY tag) AS t0 ".$qr_limit_days." ORDER BY total_hits DESC LIMIT ".$showhits.") AS t1 INNER JOIN (SELECT tag,owner,hits AS current_hits FROM ".$this->config['table_prefix']."pages WHERE latest='Y') AS t2 ON t1.tag=t2.tag ORDER BY total_hits DESC) AS t3 WHERE total_hits > '0'");
// Creating the output
$str = "\n\n<div class=\"".$class."\">\n<h2>".MOSTVISITED_HEADING."</h2>\n";
$str .= "<table class=\"mostvisited\">\n";
if ($showheader) {
$str .= "\t<tr>\n";
if ($showrank) $str .= "\t\t<th class=\"rank\">".MV_RANK."</th>\n";
if ($showowner) $str .= "\t\t<th class=\"tag\">".MV_PAGENAME_WITH_OWNER."</th>\n"; else $str .= "\t\t<th>".MV_PAGENAME."</th>\n";
if ($showcurrent) $str .= "\t\t<th class=\"current_hits\">".MV_CURRENT_VERSION_HITS."</th>\n";
if ($showtotal) $str .= "\t\t<th class=\"total_hits\">".MV_TOTAL_HITS."</th>\n";
if ($showlastvisited) $str .= "\t\t<th class=\"last_visited\">".MV_LAST_VISITED."</th>\n";
$str .= "\t</tr>\n";
}
$i = 1;
while($row = mysql_fetch_array($result))
{
if ($i%2) $str .= "\t<tr>\n"; else $str .= "\t<tr class=\"even\">\n";
if ($showrank) $str .= "\t\t<td class=\"rank\">".$i.". </td>\n";
$i+=1;$str .= "\t\t<td class=\"tag\">".$this->Format("[[".$row['tag']."]]")." ";
if ($showowner)
{
if ($row['owner'] == "") $row['owner'] = "(".MV_NOT_OWNED.")"; else if ($row['owner'] == "(Public)") $row['owner'] = "(".MV_PUBLIC_OWNED.")"; else $row['owner'] = $this->Format("([[".$row['owner']."]])");
$str .= "<span class=\"user\">".$row['owner']."</span>";
}
$str .= "</td>\n";
if ($showcurrent) $str .= "\t\t<td class=\"current_hits\">".$row['current_hits']."</td>\n";
if ($showtotal) $str .= "\t\t<td class=\"total_hits\">".$row['total_hits']."</td>\n";
if ($showlastvisited)
{
$str .= "\t\t<td class=\"last_visited\">";
if ($row['last_visited'] == '0000-00-00 00:00:00') $str .= MV_LAST_VISITED_UNKNOWN; else $str .= $row['last_visited'];
$str .= "</td>\n";
}
$str .= "\t</tr>\n";
}
$str .= "</table>\n</div>\n";
// Displaying the output
print $this->ReturnSafeHTML($str);
?>
/**
* Display a list of most visited pages.
*
* @package Actions
* @name MostVisited
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @filesource
*
* @author {@link mailto:[email protected] George Petsagourakis} (first version)
* @author {@link http://wikkawiki.org/KrzysztofTrybowski Krzysztof Trybowski} (later changes)
* @date 06 Feb 2008
*
* @description This file assumes that you are running the counter.php by GmBowen or TRBCounter on your Wakka
*/
// Default translation entries
if (!defined('MOSTVISITED_HEADING')) define('MOSTVISITED_HEADING', 'Most visited pages');
if (!defined('MV_RANK')) define('MV_RANK', 'Rank');
if (!defined('MV_PAGENAME')) define('MV_PAGENAME', 'Page name');
if (!defined('MV_PAGENAME_WITH_OWNER')) define('MV_PAGENAME_WITH_OWNER', 'Page name (page owner)');
if (!defined('MV_CURRENT_VERSION_HITS')) define('MV_CURRENT_VERSION_HITS', 'Current<br> version hits');
if (!defined('MV_TOTAL_HITS')) define('MV_TOTAL_HITS', 'Total hits');
if (!defined('MV_LAST_VISITED')) define('MV_LAST_VISITED', 'Last visited');
if (!defined('MV_LAST_VISITED_UNKNOWN')) define('MV_LAST_VISITED_UNKNOWN', '(unknown)');
if (!defined('MV_OWNER')) define('MV_OWNER', 'Owner'); //not used yet
if (!defined('MV_NOT_OWNED')) define('MV_NOT_OWNED', 'not owned');
if (!defined('MV_PUBLIC_OWNED')) define('MV_PUBLIC_OWNED', 'public');
// Defaults for options and some checking
$showhits=abs($showhits);
$limitdays=abs($limitdays);
if ($showhits==0) $showhits = 10;
if ($limitdays<1) $limitdays = '';
if (!isset($showrank)) $showrank = true;
if (!isset($showowner)) $showowner = false;
if (!isset($showcurrent)) $showcurrent = false;
if (!isset($showtotal)) $showtotal = true;
if (!isset($showheader)) $showheader = true;
if (!isset($showlastvisited)) $showlastvisited = false;
if (!isset($class)) $class = "mostvisited_container"; else $class = $this->CleanTextNode($class);
// If we should show "last visited" column, then these addictions to a query are necessary
if ($showlastvisited or $limitdays)
{
$last_visited = ", MAX(last_visited) AS last_visited ";
$last_visited2 = ",last_visited";
}
else
{
$last_visited = ""; $last_visited2 = "";
}
// Let's prepare a list of PageNames that should have counter disabled and shouldn't be listed
$disable_pages = explode(',',strtr($this->GetConfigValue('page_hit_counter_disable_pages'), array(" " => "", "'" => "")));
// Using a different variable for list in format expected by MySQL
$qr_disable_pages = array();
foreach ($disable_pages as $i => $v) if (!$v == '') array_push($qr_disable_pages, "'".$disable_pages[$i]."'");
if (count($qr_disable_pages) > 0) $qr_disable_pages = " WHERE tag NOT IN (".implode(", ", $qr_disable_pages).") "; else $qr_disable_pages='';
// Let's prepare a query addiction for limitdays
if ($limitdays) $qr_limit_days = " WHERE last_visited > SUBDATE(now(),".$limitdays.") "; else $qr_limit_days = '';
// Database query
$result = $this->Query("SELECT * FROM (SELECT t1.tag,owner,total_hits,current_hits".$last_visited2." FROM (SELECT * FROM (SELECT tag,SUM(hits) AS total_hits ".$last_visited." FROM ".$this->config['table_prefix']."pages ".$qr_disable_pages." GROUP BY tag) AS t0 ".$qr_limit_days." ORDER BY total_hits DESC LIMIT ".$showhits.") AS t1 INNER JOIN (SELECT tag,owner,hits AS current_hits FROM ".$this->config['table_prefix']."pages WHERE latest='Y') AS t2 ON t1.tag=t2.tag ORDER BY total_hits DESC) AS t3 WHERE total_hits > '0'");
// Creating the output
$str = "\n\n<div class=\"".$class."\">\n<h2>".MOSTVISITED_HEADING."</h2>\n";
$str .= "<table class=\"mostvisited\">\n";
if ($showheader) {
$str .= "\t<tr>\n";
if ($showrank) $str .= "\t\t<th class=\"rank\">".MV_RANK."</th>\n";
if ($showowner) $str .= "\t\t<th class=\"tag\">".MV_PAGENAME_WITH_OWNER."</th>\n"; else $str .= "\t\t<th>".MV_PAGENAME."</th>\n";
if ($showcurrent) $str .= "\t\t<th class=\"current_hits\">".MV_CURRENT_VERSION_HITS."</th>\n";
if ($showtotal) $str .= "\t\t<th class=\"total_hits\">".MV_TOTAL_HITS."</th>\n";
if ($showlastvisited) $str .= "\t\t<th class=\"last_visited\">".MV_LAST_VISITED."</th>\n";
$str .= "\t</tr>\n";
}
$i = 1;
while($row = mysql_fetch_array($result))
{
if ($i%2) $str .= "\t<tr>\n"; else $str .= "\t<tr class=\"even\">\n";
if ($showrank) $str .= "\t\t<td class=\"rank\">".$i.". </td>\n";
$i+=1;$str .= "\t\t<td class=\"tag\">".$this->Format("[[".$row['tag']."]]")." ";
if ($showowner)
{
if ($row['owner'] == "") $row['owner'] = "(".MV_NOT_OWNED.")"; else if ($row['owner'] == "(Public)") $row['owner'] = "(".MV_PUBLIC_OWNED.")"; else $row['owner'] = $this->Format("([[".$row['owner']."]])");
$str .= "<span class=\"user\">".$row['owner']."</span>";
}
$str .= "</td>\n";
if ($showcurrent) $str .= "\t\t<td class=\"current_hits\">".$row['current_hits']."</td>\n";
if ($showtotal) $str .= "\t\t<td class=\"total_hits\">".$row['total_hits']."</td>\n";
if ($showlastvisited)
{
$str .= "\t\t<td class=\"last_visited\">";
if ($row['last_visited'] == '0000-00-00 00:00:00') $str .= MV_LAST_VISITED_UNKNOWN; else $str .= $row['last_visited'];
$str .= "</td>\n";
}
$str .= "\t</tr>\n";
}
$str .= "</table>\n</div>\n";
// Displaying the output
print $this->ReturnSafeHTML($str);
?>
2. How to translate it
Add the following lines to your lang/xx/xx.inc.php (substitute xx for a code of your language):/**#@+
* Language constant used by the {@link mostvisited.php mostvisited} action
*/
// mostvisited
define('MOSTVISITED_HEADING', 'Most visited pages');
define('MV_RANK', 'Rank');
define('MV_PAGENAME', 'Page name');
define('MV_PAGENAME_WITH_OWNER', 'Page name (page owner)');
define('MV_CURRENT_VERSION_HITS', 'Current<br> version hits');
define('MV_TOTAL_HITS', 'Total hits');
define('MV_OWNER', 'Owner'); //not used yet
define('MV_NOT_OWNED', 'not owned');
define('MV_PUBLIC_OWNED', 'public');
define('MV_LAST_VISITED', 'Last visited');
define('MV_LAST_VISITED_UNKNOWN', '(unknown)');
/**#@-*/
* Language constant used by the {@link mostvisited.php mostvisited} action
*/
// mostvisited
define('MOSTVISITED_HEADING', 'Most visited pages');
define('MV_RANK', 'Rank');
define('MV_PAGENAME', 'Page name');
define('MV_PAGENAME_WITH_OWNER', 'Page name (page owner)');
define('MV_CURRENT_VERSION_HITS', 'Current<br> version hits');
define('MV_TOTAL_HITS', 'Total hits');
define('MV_OWNER', 'Owner'); //not used yet
define('MV_NOT_OWNED', 'not owned');
define('MV_PUBLIC_OWNED', 'public');
define('MV_LAST_VISITED', 'Last visited');
define('MV_LAST_VISITED_UNKNOWN', '(unknown)');
/**#@-*/
...replacing English texts with your translations.
3. How to format/skin the output
The whole output of the action is included in a div with mostvisited_containter class. It contains page title within <h2> tag and a table with mostvisited class. The while output contains classes, so it's easy to be skinned -- for details see the source.My proposed formatting for the action (place it in yoour css/wikka.css file):
.mostvisited { margin-top: 1em; border-collapse: collapse}
.mostvisited th { background: #e3e3e3; padding: 0 0.5em; border: 1px solid #cccccc;}
.mostvisited td { background: #fafafa; padding: 0 1em; border: 1px solid #e3e3e3;}
.mostvisited .even td { background: #f0f0f0; }
.mostvisited td.rank, .mostvisited td.current_hits, .mostvisited td.total_hits { text-align: right; }
.mostvisited .user { font-size: smaller; }
.mostvisited th { background: #e3e3e3; padding: 0 0.5em; border: 1px solid #cccccc;}
.mostvisited td { background: #fafafa; padding: 0 1em; border: 1px solid #e3e3e3;}
.mostvisited .even td { background: #f0f0f0; }
.mostvisited td.rank, .mostvisited td.current_hits, .mostvisited td.total_hits { text-align: right; }
.mostvisited .user { font-size: smaller; }
That's all folks. Best regards -- KrzysztofTrybowski
CategoryUserContributions