Strict Standards: Declaration of action_plugin_jquery::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /membri/only4mods/lib/plugins/jquery/action.php on line 14

Strict Standards: Declaration of action_plugin_captcha::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /membri/only4mods/lib/plugins/captcha/action.php on line 137

Strict Standards: Declaration of action_plugin_wikistatistics::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /membri/only4mods/lib/plugins/wikistatistics/action.php on line 51

Strict Standards: Declaration of action_plugin_codehighlight::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /membri/only4mods/lib/plugins/codehighlight/action.php on line 225

Strict Standards: Declaration of action_plugin_ipban::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /membri/only4mods/lib/plugins/ipban/action.php on line 60
counterize_ii_mod:en:changes - Ema's plugins (WP, DW)

Unfortunately, some of the pages are now read-only, this because in the last few months some spammers decided to “contribute” to the wiki…
I'm trying to lock only the interested pages.

Questa è una vecchia versione del documento!


History counter

Sometimes happened that I want to know how many records history is showing (for example if I'm doing a filter and the amount of data is lower that the “number of row to show” limit).
In order to obtain this I added a counter in the function “counterize_show_history” and I “echoed” it in the table.

Functions modified in counterize.php

History counter: counterize_show_history

In the explanation below I started from the results of the modification Multiple Entry Kill

Original code:
                <td scope="col" width="3%"><strong><?php _e("Kill",'counterize'); ?></strong></td></tr>
                <?php foreach($entries as $entry) { ?>
        <tr <?php if($i%2) { print "class=\"alternate\""; } ?>>
                                <td scope="col" width="6%"><small> 
								<input type="checkbox" name='counterize_killemall[<?php echo $entry->id; ?>]'
            value="<?php echo $entry->id; ?>" />
Modified code:
                <td scope="col" width="3%"><strong><?php _e("Kill",'counterize'); ?></strong></td></tr>
                <?php $entrycounter = 1;
                foreach($entries as $entry) { ?>
        <tr <?php if($i%2) { print "class=\"alternate\""; } ?>>
                                <td scope="col" width="6%"><small> <?php echo ($entrycounter."  "); $entrycounter++; ?>
								<input type="checkbox" name='counterize_killemall[<?php echo $entry->id; ?>]'
            value="<?php echo $entry->id; ?>" />

IP-Range filter

I would like to be able to filter the records by IP-range and not only by exact IP.
It's not so difficult, the only thing to do is define a new parameter that can be passed by URL as did with Visits with same URL and referer not count change.

Functions modified in counterize.php

IP-Range filter: counterize_getentries

I only added another case to the list of possible arguments passed via URL that build the “main” query.
To note that I used the operator “LIKE” instead of ”=” in order to compare the pattern.

Original code:
function counterize_getentries($amount = 50, $entryID = null)
{
    $wpdb =& $GLOBALS['wpdb'];
    $sql =  'SELECT id, ip, timestamp, p.url as url, r.name as referer, ua.name as useragent, ';
    $sql .= 'm.refererID, m.agentID, m.pageID, k.keyword, k.keywordID ';
    $sql .= "FROM ".
      counterize_logTable(). " m, " .
      counterize_pageTable(). " p, " .
      counterize_agentsTable(). " ua, " .
      counterize_refererTable(). " r, " .
      counterize_keywordTable(). " k ";
    $sql .= "WHERE m.pageID = p.pageID and m.agentID = ua.agentID and m.refererID = r.refererID ";
    $sql .= " and k.keywordID = r.keywordID and ";
 
    if($_GET["ipfilter"])
      $sql .= " m.ip = '" . $_GET["ipfilter"] ."' and ";
Modified code:
function counterize_getentries($amount = 50, $entryID = null)
{
    $wpdb =& $GLOBALS['wpdb'];
    $sql =  'SELECT id, ip, timestamp, p.url as url, r.name as referer, ua.name as useragent, ';
    $sql .= 'm.refererID, m.agentID, m.pageID, k.keyword, k.keywordID ';
    $sql .= "FROM ".
      counterize_logTable(). " m, " .
      counterize_pageTable(). " p, " .
      counterize_agentsTable(). " ua, " .
      counterize_refererTable(). " r, " .
      counterize_keywordTable(). " k ";
    $sql .= "WHERE m.pageID = p.pageID and m.agentID = ua.agentID and m.refererID = r.refererID ";
    $sql .= " and k.keywordID = r.keywordID and ";
 
    if($_GET["ipfilterrange"])
      $sql .= " m.ip LIKE '" . $_GET["ipfilterrange"] ."%' and ";
    if($_GET["ipfilter"])
      $sql .= " m.ip = '" . $_GET["ipfilter"] ."' and ";

IP Range exclude list

It's not really a list, for now it's only a bunch of IPs.

Functions modified in counterize.php

IP Range Exclude list: counterize_add

The principle is: explode the IP address, compare the first piece if it's in our exclusion list compare the second part if it's one of that we want to exclude assign 1 to $checkval.

Original code:
        elseif (stristr($requesturl, ".gif"))
                $checkval = 1;
 
        # If not found anything unwanted yet, check to see if it's on the excludelist...
        if ($checkval == 0)
Modified code:
        elseif (stristr($requesturl, ".gif"))
                $checkval = 1;
 
        if ($checkval == 0)
        {
                $IPExploded = explode(".", $remoteaddr);
                if ($IPExploded[0]==63)
                {
                        if (208 <= $IPExploded[1] && $IPExploded[1] <= 215 )
                        {
                                $checkval=1;
                        }
                }
                if ($IPExploded[0]==38)
                {
                        $checkval=1;
                }
                if ($IPExploded[0]==65)
                {
                        if ($IPExploded[1] == 222)
                        {
                                $checkval=1;
                        }
                }
                if ($IPExploded[0]==206)
                {
                        if ($IPExploded[1] == 188)
                        {
                        if (0 <= $IPExploded[2] && $IPExploded[2] <= 31 )
                                {
                                        $checkval=1;
                                }
                        }
                }
                if ($IPExploded[0]==91)
                {
                        if ($IPExploded[1] == 124)
                        {
                                $checkval=1;
                        }
                }
 
        }
        # If not found anything unwanted yet, check to see if it's on the excludelist...
        if ($checkval == 0)
Under development NOT TESTED code:
        elseif (stristr($requesturl, ".gif"))
                $checkval = 1;
 
        if ($checkval == 0)
        {
			$MultiIPExcludeList = array("63.208","63.209","63.210","63.211","63.212","63.213","63.214","63.215");
			$IPExploded = explode(".", $remoteaddr);
			foreach ($MultiIPExcludeList as $SingleIPToExclude)
			{
				$IPChecked = 0;
				$IPPartToExclude = explode(".", $SingleIPToExclude);
				for ($i = 0; $i < count($IPPartToExclude); ++$i)
				{
					if ($IPExploded[0]==$IPPartToExclude[$i])
					{
						++$IPChecked;
						break;
					}
				}
				if (count($IPPartToExclude) == $IPChecked)
				{
					$checkval = 1;
					break;
				}
			}
        }


Visits with same URL and referer not count

Some times spammers arrive with referers that are the same page visited (of course is not the only case, but others are not so frequent), I don't like to keep track of spammers so this is a “workaround”.
In addition I setup another filter that allow to find all the visits (already in the DB) where URL and referer are exactly the same address.
In order to recall this filter is necessary to use an URL like:

http://www.yoursite.com/pathtoblog/wp-admin/edit.php?page=counterize/counterize.php&sameRefUrl=1

Functions modified in counterize.php

URL referer count: counterize_add

The first step is to “re-build” the actual URL in the variable “$this_url”:

Original code:
         if ($_SERVER['HTTP_REFERER'])
                $referer = $_SERVER['HTTP_REFERER'];
        # Check to see if we really want to insert the entry...
Modified code:
         if ($_SERVER['HTTP_REFERER'])
                $referer = $_SERVER['HTTP_REFERER'];
         $this_url = "http://".$_SERVER['HTTP_HOST'].$requesturl; 
        # Check to see if we really want to insert the entry...


Now that we have obtained the URL it is possible to compare it with the referer:

Original code:
        if ($checkval == 0)
        {
                // Exclude RSS feeds (Both with and without permalinks)
                // Stating just feed would make it impossible to name a page or post 'feed'
                if (stristr($requesturl, "feed/"))
                        $checkval = 1;
Modified code:
        if ($checkval == 0)
        {
                // Exclude if referer is the same as url
                if ($this_url==$referer )
                        $checkval = 1;
                // Exclude RSS feeds (Both with and without permalinks)
                // Stating just feed would make it impossible to name a page or post 'feed'
                if (stristr($requesturl, "feed/"))
                        $checkval = 1;

URL referer count: counterize_getentries

I only added another case to the list of possible arguments passed via URL that build the “main” query. Because the page URL is stored without host I used the CONCAT command anche the php variable $_SERVER['HTTP_HOST'] in order “re-build” the full addresses and compare it with the referer:

Original code:
function counterize_getentries($amount = 50, $entryID = null)
{
    $wpdb =& $GLOBALS['wpdb'];
    $sql =  'SELECT id, ip, timestamp, p.url as url, r.name as referer, ua.name as useragent, ';
    $sql .= 'm.refererID, m.agentID, m.pageID, k.keyword, k.keywordID ';
    $sql .= "FROM ".
      counterize_logTable(). " m, " .
      counterize_pageTable(). " p, " .
      counterize_agentsTable(). " ua, " .
      counterize_refererTable(). " r, " .
      counterize_keywordTable(). " k ";
    $sql .= "WHERE m.pageID = p.pageID and m.agentID = ua.agentID and m.refererID = r.refererID ";
    $sql .= " and k.keywordID = r.keywordID and ";
 
    if($_GET["ipfilter"])
      $sql .= " m.ip = '" . $_GET["ipfilter"] ."' and ";
Modified code:
function counterize_getentries($amount = 50, $entryID = null)
{
    $wpdb =& $GLOBALS['wpdb'];
    $sql =  'SELECT id, ip, timestamp, p.url as url, r.name as referer, ua.name as useragent, ';
    $sql .= 'm.refererID, m.agentID, m.pageID, k.keyword, k.keywordID ';
    $sql .= "FROM ".
      counterize_logTable(). " m, " .
      counterize_pageTable(). " p, " .
      counterize_agentsTable(). " ua, " .
      counterize_refererTable(). " r, " .
      counterize_keywordTable(). " k ";
    $sql .= "WHERE m.pageID = p.pageID and m.agentID = ua.agentID and m.refererID = r.refererID ";
    $sql .= " and k.keywordID = r.keywordID and ";
 
    if($_GET["sameRefUrl"])
      $sql .= " CONCAT('".$_SERVER['HTTP_HOST']."', p.url) = r.name and ";
    if($_GET["ipfilter"])
      $sql .= " m.ip = '" . $_GET["ipfilter"] ."' and ";


Geo IP Tool

For some days Geo IP Tool stop to work properly, when a query was performed it showed a 404 - page not found and anything else…
In order to overcome the problem I changed the URL in Counterize II.
In short I changed the URL from ”http://www.geoiptool.com/en/?IP=” to ”http://www.geoiptool.com/?IP=” note that the “en/” is now absent.

Now Geo IP Tool is working properly again, but may happen again

Functions modified in counterize.php

Modifications

Geo IP Tool: counterize_most_visited_ips

Original code:
$sql = "SELECT COUNT(IP) AS amount, IP as label, concat('http://www.geoiptool.com/en/?IP=',IP) as url
  FROM ".counterize_logTable()." GROUP BY IP ORDER BY amount DESC LIMIT $number";
Modified code:
$sql = "SELECT COUNT(IP) AS amount, IP as label, concat('http://www.geoiptool.com/?IP=',IP) as url
  FROM ".counterize_logTable()." GROUP BY IP ORDER BY amount DESC LIMIT $number";

Geo IP Tool: counterize_show_history

Original code:
<td scope="col" width="10%"><small><?php echo "<a href=\"" . get_option("counterize_whois") . $entry->ip . "\">" . $entry->ip . "</a>"; ?>
(<a href="edit.php?page=counterize/counterize.php&ipfilter=<?php echo $entry->ip; ?>">F</a>)
(<a target="_blank" href="http://www.geoiptool.com/en/?IP=<?php echo $entry->ip; ?>">V</a>)</small> </td>
Modified code:
<td scope="col" width="10%"><small><?php echo "<a href=\"" . get_option("counterize_whois") . $entry->ip . "\">" . $entry->ip . "</a>"; ?>
(<a href="edit.php?page=counterize/counterize.php&ipfilter=<?php echo $entry->ip; ?>">F</a>)
(<a target="_blank" href="http://www.geoiptool.com/?IP=<?php echo $entry->ip; ?>">V</a>)</small> </td>




Multiple Entry kill

As first step I introduced a functionality that allow to kill more than one entry at a time.

Functions modified in counterize.php

Functions modified in counterize_killemall.php

Modifications

Multiple Entry kill: counterize_show_history

The table is now included in a <form> tag, in addition a new column is added to the table itself.
The form tag point to a new file counterize_killemall.php that execute the deletion routines.
The parameter ”&killemall=OfCourse” is present only because I think it can be useful later in order to add new functionality…but maybe not…

Original code:
    <div class="wrap">
        <h2>
        <?php echo $howmany; ?>
        </h2>
 
 
        <a href="edit.php?page=counterize/counterize.php"><?php _e("Reset Filters",'counterize'); ?></a></br></br>
                <table width="100%" cellpadding="3" cellspacing="3">
                <tr class="alternate">
                <td scope="col" width="6%"><strong><?php _e("ID",'counterize'); ?></strong></td>
                <td scope="col" width="13%"><strong><?php _e("IP",'counterize'); ?></strong></td>
Modified code:
    <div class="wrap">
        <h2>
        <?php echo $howmany; ?>
        </h2>
 
        <a href="edit.php?page=counterize/counterize.php"><?php _e("Reset Filters",'counterize'); ?></a></br></br>
<form method="post" action="edit.php?page=counterize/counterize_killemall.php&amp;killemall=OfCourse" name="tablesForm" id="tablesForm">
                <table width="100%" cellpadding="3" cellspacing="3">
                <tr class="alternate">
                <td scope="col" width="2%"><strong><?php _e("del",'counterize'); ?></strong></td>
                <td scope="col" width="6%"><strong><?php _e("ID",'counterize'); ?></strong></td>
                <td scope="col" width="13%"><strong><?php _e("IP",'counterize'); ?></strong></td>

In the new column I introduced a checkbox for each entry visualized. This will be the way to select entry that must be deleted later.

Original code:
        <tr <?php if($i%2) { print "class=\"alternate\""; } ?>>
                                <td scope="col" width="6%"><small><?php echo $entry->id; ?></small> </td>
                                <td scope="col" width="10%"><small><?php echo "<a href=\"" . get_option("counterize_whois") . $entry->ip . "\">" . $entry->ip . "</a>"; ?>
            (<a href="edit.php?page=counterize/counterize.php&ipfilter=<?php echo $entry->ip; ?>">F</a>)
            (<a target="_blank" href="http://www.geoiptool.com/en/?IP=<?php echo $entry->ip; ?>">V</a>)</small> </td>
                                <td scope="col" width="14%"><small><?php echo $entry->timestamp; ?> </small></td>
                                <td scope="col" width="25%"><small><?php echo "<a href=\"" . $entry->url . "\">" . wordwrap($entry->url, 30, "\n", 1); ?> </a>
          (<a href="edit.php?page=counterize/counterize.php&urifilter=<?php echo $entry->url; ?>">F</a>)</small></td>
                                <td scope="col" width="20%"><small>
                                <?php
                                if ($entry->referer != "unknown")
Modified code:
        <tr <?php if($i%2) { print "class=\"alternate\""; } ?>>
                                <td scope="col" width="6%"><small>
								<input type="checkbox" name='counterize_killemall[<?php echo $entry->id; ?>]'
            value="<?php echo $entry->id; ?>" />
            <!--id="checkbox_entry_<?php //echo $entry->id; ?>" />-->  </td> <td>
 
								<?php echo $entry->id; ?></small> </td>
                                <td scope="col" width="10%"><small><?php echo "<a href=\"" . get_option("counterize_whois") . $entry->ip . "\">" . $entry->ip . "</a>"; ?>
            (<a href="edit.php?page=counterize/counterize.php&ipfilter=<?php echo $entry->ip; ?>">F</a>)
            (<a target="_blank" href="http://www.geoiptool.com/?IP=<?php echo $entry->ip; ?>">V</a>)</small> </td>
                                <td scope="col" width="14%"><small><?php echo $entry->timestamp; ?> </small></td>
                                <td scope="col" width="25%"><small><?php echo "<a href=\"" . $entry->url . "\">" . wordwrap($entry->url, 30, "\n", 1); ?> </a>
          (<a href="edit.php?page=counterize/counterize.php&urifilter=<?php echo $entry->url; ?>">F</a>)</small></td>
                                <td scope="col" width="20%"><small>
                                <?php
                                if ($entry->referer != "unknown")

Of course something is needed also at the end of the table…
Three buttons: one is the form's “submit”, the others two are a “select all” and a “deselect all” (of course only the visible entries! ;-) ).

Original code:
                <?php
                  $i++;
      }
      ?>
        </tr></table>
  </div>
 
  <?php
 
}
Modified code:
                <?php
                  $i++;
      }
      ?>
        </tr></table>
 
<input type="button" name="CheckAll"   value="Check All"
	//onClick="checkAll(document.tablesForm)" />
<input type="button" name="UnCheckAll" value="Uncheck All"
	//onClick="uncheckAll(document.tablesForm)" />
<input type="SUBMIT" value="Kill selected" />
 
</form>
  </div>
 
  <?php
 
}

Multiple Entry kill: counterize_manage_page

In order to allow the selection and delesection of all the (visible) entries at a time I added two buttons in counterize_show_history, but those two needs a javascript to work, and here is it!
Nothig special, I found it on internet and I adapted it.

Original code:
function counterize_manage_page()
{
  ?><script language="javascript" type="text/javascript">
        function conf(url)
        {
                if (confirm('<?php _e('Are you sure that you want to delete this entry?','counterize'); ?>'))
                {
                        self.location.href = url;
                }
        }
  </script>
  <?php
 
  # For the zap-an-entry-option
Modified code:
function counterize_manage_page()
{
  ?><script language="javascript" type="text/javascript">
        function conf(url)
        {
                if (confirm('<?php _e('Are you sure that you want to delete this entry?','counterize'); ?>'))
                {
                        self.location.href = url;
                }
        }
<!--
// by Nannette Thacker
// http://www.shiningstar.net
// This script checks and unchecks boxes on a form
// Checks and unchecks unlimited number in the group...
// Pass the Checkbox group name...
// call buttons as so:
// <input type=button name="CheckAll"   value="Check All"
	//onClick="checkAll(document.myform.list)">
// <input type=button name="UnCheckAll" value="Uncheck All"
	//onClick="uncheckAll(document.myform.list)">
//-->
 
<!-- Begin
function checkAll(field)
{
for (i = 0; i < field.length; i++)
	field[i].checked = true ;
}
 
function uncheckAll(field)
{
for (i = 0; i < field.length; i++)
	field[i].checked = false ;
}
//  End --></script>
 
  <?php
 
  # For the zap-an-entry-option

Multiple Entry kill: no functions

The file “counterize_killemall.php” is new to counterize, I introduced it in order to reduce to the minimum the modification to the original counterize.php file.
The function is really basic: it check if a “killemall” variable is specified and if it's equal to “OfCourse”, after that it check if the POST is passed by the “SUBMIT” button and finally the counterize II function “counterize_killEntry($val)” is called for each ID passed in the POST.
For each entry deleted in the admin page a string reporting the ID of the entry is visualized.
I just added a small change: when the kill process is finished then the link at the end of the page will point to the previous page, that means usually the main page of counterize, but in certain cases can be for example the main page but with a filte on IPs. This function is still experimental, because I wrote it without test!!
TODO1 introduce a warning before start the delete process.

Original code:
<?php
if (isset($_GET['killemall']))
{
	if ($_GET['killemall']=='OfCourse')
	{
		if (isset($_POST['counterize_killemall']))
		{
			foreach ($_POST['counterize_killemall'] as $key => $val)
			{
				counterize_killEntry($val);
				_e('Entry: '.$val.' removed<br />','counterize');
			}
		} ?>
		<br /><a href="edit.php?page=counterize\counterize.php">
		<?php _e('Come back to Counterize','counterize'); ?>
		</a> 
<?php
	}
}
?>
Modified code:
<?php
<?php
if (isset($_GET['killemall']))
{
	if ($_GET['killemall']=='OfCourse')
	{
		if (isset($_POST['counterize_killemall']))
		{
			foreach ($_POST['counterize_killemall'] as $key => $val)
			{
				counterize_killEntry($val);
				_e('Entry: '.$val.' removed<br />','counterize');
			}
		}
		if ($_SERVER['HTTP_REFERER'])
		{
			$referer = $_SERVER['HTTP_REFERER'];
		}
		else
		{
			$referer = "edit.php?page=counterize/counterize.php";
		}
		echo("<br /><a href=\"".$referer."\">");
		_e('Back to Counterize','counterize');
		echo("</a>");
	}
}
?>




New bot's useragent

A list of bot's useragent discovered by looking at the logs:

        $botarray[] = "Pagebull";
        $botarray[] = "HTTrack";
        $botarray[] = "OffByOne";
        $botarray[] = "PrintSmart";
        $botarray[] = "Getleft";
        $botarray[] = "Indy Library";
        $botarray[] = "DE Slurp";
        $botarray[] = "compatible; ICS";
        $botarray[] = "Powermarks";
        $botarray[] = "C-CCK-MCD";
        $botarray[] = "depspid";
        $botarray[] = "Twingly Recon";
        $botarray[] = "Netcraft";
        $botarray[] = "Check&amp;Get";
        $botarray[] = "relevantnoise";
        $botarray[] = "LiteFinder";
        $botarray[] = "Gigamega";
        $botarray[] = "Wget";
        $botarray[] = "Java/1.5";
        $botarray[] = "publisher.yahoo.com/rssguide";

New ideas

  • a way to see previous entries
  • aggregation of search engines referers (to me is not important in details the search string used by the visitor, I prefer to know how many visitors arrived to my blog using google (or maybe google.com, google.it, it.yahoo.com and so on) and how many using yahoo and so on, in addition this solution will save a lot of db space!)
  • transfer the bot exclusion list from code to database
  • introduce an easy way to add or remove bot user agents by admin panel (see previous point).
  • and most important a “archive” function that will clean-up the database keeping only summary of the statistics (in order to save space)
  • Multiple filters (already possible, it's enough to add it to the URL in the address bar)


Archive function

Considerations

  • First of all the list of statistics that I would like to save:
    1. total hits → counterize_getamount()
    2. hits from unique IPs → counterize_getuniqueamount()
    3. visits based on day of month → counterize_getdailystats()
    4. visits based on day of week → counterize_getweeklystats()
    5. visits based on month → counterize_getmonthlystats()
    6. visits based on day of hour of day → counterize_gethourlystats()


  • Second why I didn't talk about “most visited IPs”. 1) Consider this statistic means to have a final “archive” with at least one third of the original records in the “wp_counterize” table; yes, this doesn't means to have also an equivalent amount of bits space used, but in any case the final gain in term of space will be smaller. So, at least for now, I will not consider these data. 2) In my country the number of people with a static IP Address is trifling, this means that the IP is useful only to detect spiders and spammers, not to identify unique visitors in the long-period.


  • Third why I didn't mention most visited pages and so on. That's easy: because at the moment I don't want to archive them.
  • Fourth what do the functions return?
function return string data type
counterize_getamount return $wpdb->get_var($sql); number
counterize_getuniqueamount return $wpdb->get_var($sql); number
counterize_getdailystats return $wpdb->get_results($sql); matrix *
counterize_getweeklystats return $wpdb->get_results($sql); matrix *
counterize_getmonthlystats return $wpdb->get_results($sql); matrix *
counterize_gethourlystats return $wpdb->get_results($sql); matrix *

*) Used as:

foreach($rows as $row)
{
...
   $row->amount;
   $row->label;
...
}

Check function “counterize_renderstats”

So, the functions are all ready, the only thing is to think about the table structure…
Here it is my first attempt:

archID time type value

archID => an incremental number
time => timestamp of the day/hour/minutes when the archive function is executed
type => a string that represent the information stored (total hits, hits from unique IPs, ecc.)

function string type description
counterize_getamount amount
counterize_getuniqueamount uniqueamount
counterize_getdailystats dailystats_[$row→label]
counterize_getweeklystats weeklystats_[$row→label]
counterize_getmonthlystats monthlystats_[$row→label] *
counterize_gethourlystats hourlystats_[$row→label]

* In this case the values returned by $row→label are formatted like “mmm YY”, where “mmm” is an abbreviation of the month name (i.e. “Jan”, “Feb”, “Mar”), and “YY” is a two digit numerical representation of the year the data were collected (i.e. “06”, “07”, and so on). For this reason in this case the value must be processed in order to obtain only the “mmm” part. I think that something like: $label = split(” ”, $row→label) is enough, and after use only $label[0] instead of $row→label.

value => the value of the information stored (number of total hits, number of hits from unique IPs, ecc.), in other words the value returned from the functions counterize_getamount(), counterize_getuniqueamount(), ecc.

  • Fifth and final consideration: I can develop this as a stand-alone plugin.

Let's code!

ATTENTION: The following code is not tested!!

It's time to star write some code.
At least two piece of code are necessary:

  1. the first for installation procedure
  2. the second for the function it self.

Installation
In the install process I need to create the table if it don't exist.
I used the counterize II install procedure as “template”… ^^

function archived_counterize_install()
{ 
  $MajorVersion = get_option('archived_counterize_MajorVersion');
  $MinorVersion = get_option('archived_counterize_MinorVersion');
 
  $wpdb =& $GLOBALS['wpdb'];
 
  if($MajorVersion == 0 && $MinorVersion == 0)
  {
    $sql = 'SHOW TABLES LIKE \''archived_counterize_logTable().'\'';
    $results = $wpdb->query($sql);
 
    if ($results == 0)
    {
      $sql = "create table ".archived_counterize_logTable()."
        (
        `archID` integer not null auto_increment,
        `year` SMALLINT UNSIGNED NOT NULL,
        `time` timestamp NOT NULL,
        `type` varchar(255) not null default 'unknown',
        `value` MEDIUMINT NOT NULL default '1',
        primary key(archID)
        )";
 
      $wpdb->query($sql);
    }
  }
 
  update_option('archived_counterize_MajorVersion',0);
  update_option('archived_counterize_MinorVersion',1);
}

Plugin
The first thing I need is a “clone” of the original counterize functions that return value I'll archive (i.e. the ones listed above), and that will substitute the original counterize in templates. In these functions I'll call the original counterize functions in order to get the actual number of visits, unique visits and so on, in addition I'll query the table created during install (wp_counterize_archive or something like that, I haven't decide yet the name… :-P )

function archived_counterize_logTable()
{
return $GLOBALS['table_prefix'] . "archived_counterize";
}
 
function archived_counterize_getamount()
{
$sql = 'SELECT SUM(value) FROM ' . archived_counterize_logTable() . 'where type = amount';
$wpdb =& $GLOBALS['wpdb'];
$archived = $wpdb->get_var($sql);
 
if function_exists('counterize_getamount')
   {
      return counterize_getamount() + $archived;
   }
else
   {
      return $archived;
   }
}
function archived_counterize_getuniqueamount()
{
$sql = 'SELECT SUM(value) FROM ' . archived_counterize_logTable() . 'where type = amount';
$wpdb =& $GLOBALS['wpdb'];
$archived = $wpdb->get_var($sql);
 
if function_exists('counterize_getuniqueamount')
   {
      return counterize_getuniqueamount() + $archived;
   }
else
   {
      return $archived;
   }
}
 
function archived_counterize_getdailystats($only_this_month = false)
{
//"$only_this_month" kept for compatibility
  $wpdb =& $GLOBALS['wpdb'];
  if function_exists('counterize_getdailystats')
  {
    $actual = counterize_getdailystats($only_this_month);
  }
  if($only_this_month && isset($actual))
  {
    return $actual;
  }
  else
  {
//I'm not sure about the query...I've to test it.
    $sql = "SELECT type as label, SUM(value) as amount FROM " . archived_counterize_logTable() . " group by label WHERE type LIKE 'dailystats_%'";
    $archived = $wpdb->get_results($sql);
/*    for($i=0; $i<=array_count_values($archived); $i++)
    {
      $ID = split("_", $row->label);
      $archived[$i]->label = $ID[1];
    }*/
    if(isset($actual))
    {
      $archived = archived_sumcontents($archived, $actual);
    }
    return $archived;
  }
}
 
function archived_counterize_getweeklystats()
{
  $wpdb =& $GLOBALS['wpdb'];
  if function_exists('counterize_getweeklystats')
  {
    $actual = counterize_getweeklystats();
  }
//I'm not sure about the query...I've to test it.
    $sql = "SELECT type as label, SUM(value) as amount FROM " . archived_counterize_logTable() . " group by label WHERE type LIKE 'weeklystats_%'";
    $archived = $wpdb->get_results($sql);
/*    for($i=0; $i<=array_count_values($archived); $i++)
    {
      $ID = split("_", $row->label);
      $archived[$i]->label = $ID[1];
    }*/
    if(isset($actual))
    {
      $archived = archived_sumcontents($archived, $actual);
    }
    return $archived;
}
 
function archived_counterize_getmonthlystats()
{
  $wpdb =& $GLOBALS['wpdb'];
  if function_exists('counterize_getmonthlystats')
  {
    $actual = counterize_getmonthlystats();
  }
//I'm not sure about the query...I've to test it.
    $sql = "SELECT type as label, SUM(value) as amount FROM " . archived_counterize_logTable() . " group by label WHERE type LIKE 'monthlystats_%'";
    $archived = $wpdb->get_results($sql);
/*    for($i=0; $i<=array_count_values($archived); $i++)
    {
      $ID = split("_", $row->label);
      $archived[$i]->label = $ID[1];
    }*/
    if(isset($actual))
    {
      $archived = archived_sumcontents($archived, $actual, true);
    }
    return $archived;
}
 
function archived_counterize_gethourlystats()
{
  $wpdb =& $GLOBALS['wpdb'];
  if function_exists('counterize_gethourlystats')
  {
    $actual = counterize_gethourlystats();
  }
//I'm not sure about the query...I've to test it.
    $sql = "SELECT type as label, SUM(value) as amount FROM " . archived_counterize_logTable() . " group by label WHERE type LIKE 'hourlystats_%'";
    $archived = $wpdb->get_results($sql);
/*    for($i=0; $i<=array_count_values($archived); $i++)
    {
      $ID = split("_", $row->label);
      $archived[$i]->label = $ID[1];
    }*/
    if(isset($actual))
    {
      $archived = archived_sumcontents($archived, $actual);
    }
    return $archived;
}
 
function archived_sumcontents($archived, $actual, $ismonth = false)
{
    for($i=0; $i<=array_count_values($archived); $i++)
    {
      $ID = split("_", $row->label);
      $archived[$i]->label = $ID[1];
    }
    for($i=0; $i<=array_count_values($archived); $i++)
    {
      foreach($actual as $act_row)
      {
        if($ismonth){$temp = split(" ", $act_row->label); $act_row->label = $temp[0];}
        if($archived[$i]->label == $act_row->label)
        {
          $archived[$i]->amount += $act_row->amount;
        }
      }
    }
    return $archived;
}

Cloned the function that retrieve data, now I have to create the function to archive data.

function archived_archive()
{
  $timestamp = gmdate("Y-m-d H:i:s",time() + ( get_option('gmt_offset') * 60 * 60 ));
  $wpdb =& $GLOBALS['wpdb'];
  $basesql = "INSERT INTOP " . archived_counterize_logTable() . " (time, type, value) VALUES ('" . $timestamp . "'";
/*  $sql = $basesql . "'" . $timestamp . "'";*/
  $sql = $basesql "'amount'";
  $sql .= "'" . counterize_getamount() . "'";
  $results = $wpdb->query($sql);
 
  $sql = $basesql "'uniqueamount'";
  $sql .= "'" . counterize_getuniqueamount() . "'";
  $results = $wpdb->query($sql);
 
  $dailystats = counterize_getdailystats();
  foreach ($dailystats as $day)
  {
    $sql = $basesql "'dailystats_". $day->label ."'";
    $sql .= "'" . $day->amount . "'";
    $results = $wpdb->query($sql);
  }
 
  $weeklystats = counterize_getweeklystats();
  foreach ($weeklystats as $week)
  {
    $sql = $basesql "'weeklystats_". $week->label ."'";
    $sql .= "'" . $week->amount . "'";
    $results = $wpdb->query($sql);
  }
 
  $monthlystats = counterize_getmonthlystats();
  foreach ($monthlystats as $month)
  {
    $temp = split(" ", $month->label);
    $sql = $basesql "'monthlystats_". $temp[0] ."'";
    $sql .= "'" . $month->amount . "'";
    $results = $wpdb->query($sql);
  }
 
  $hourlystats = counterize_gethourlystats();
  foreach ($hourlystats as $hour)
  {
    $sql = $basesql "'hourlystats_". $hour->label ."'";
    $sql .= "'" . $hour->amount . "'";
    $results = $wpdb->query($sql);
  }
 
}

Tools personali