<?php
/*
Plugin Name: Boakes MostWanted
Plugin URI: http://www.boakes.org/most-wanted
Description: This plugin uses the StatTraq table to report on the most popular pages based on the number of times each has been viewed
Author: Rich Boakes
Author URI: http://boakes.org/
Version: 0.1.5
License: http://creativecommons.org/licenses/by-nc-sa/2.0/
*/

$ver "0.1.6";

/*
// Rich Boakes would like it recognized that:
//   Randy Peterman, Ben Gracewood, Darryl VanDorp,
//   Michelle Li, Rodney Shupe, Mike Smith
// have provided inspired suggestions, and code, that is
// either part of the plugin, or which the plugin
// makes use of via StatTraq.
//
// Thanks too to everyone who's used, abused and repaired
// the various generations of this plugin and fed that
// knowledge back to me for the benefit of all.
//
// Release History
//
//   version 0.0.1
//     original release
//   version 0.0.2
//     improved code to allow the top "n" results to be displayed and
//     also to give the user control on how the text is curtailed. also
//     the number of views can optionally be displayed.
//   version 0.0.3
//     tweaked "the top-two posts" issue
//     added a possible solution to the escaping problem (feedback invited)
//   version 0.0.4
//     modified to use the $tableposts variable which may help users with
//     multiple blogs through different users.
//   version 0.0.5 (not released separately)
//     added the option to display the count in the tooltip.
//   version 0.0.6
//     recognizes and omits entries with the spam flag in stattraq db
//     (disabled by default).
//   version 0.0.7
//     added the fixStats method to repair any older statistics that do not
//     include the post ID.
//   version 0.1.0
//     api name change
//     added a duration parameter which is an integrer representing the
//     number of days that are of interest.
//     added the ability to set pre and post output strings.
//     small change to fixstats to only alter published posts.
//     permalinks are now used instead of page id.
//   version 0.1.1
//     fixed a small problem with the wrapper where $duration wasn't set.
//     added advice about not adding spaces or newlines after last line.
//   version 0.1.2
//     option to select method of user count (IP addr / session id)
//     removed commented query from body of resulting output
//   version 0.1.3
//     fixed the "Missing argument 5 for mostwanted()" bug
//   version 0.1.4
//     fixed a bug where a titles that contain an apostrophe were not
//     being properly escaped in the tooltip, resulting in non-validating
//     output.
//     added comment signature to output, so folks who see the feature and
//     want to use it will know where to come looking
//   version 0.1.5
//     added capability to display percentage of total hits instead of the
//     number of hits, for those that don't want the intimacies of their
//     traffic to be broadcast.
//     Slight title change to "Boakes MostWanted" so that it exists with
//     all the other plugins I've written for my site.
//   version 0.1.6
//     improved the curtail function so that a $curtail value of 0 returns 
//     the full original string.
//     altered the comment signature so it's more easy for me to see who's
//     using older (deprecated) versions of the plugin through a non-visible
//     link to the most-wanted web page - it's now placed in the page footer
//     too, which makes it far easier to find.
//
// Usage:
//
//   MostWanted::mostwanted($top_n, $curtail, $showviews, $show_views_in_tt, $duration, $cat, $pre, $post, $method)
//
//   $top_n             the number of results to list
//                      default = 5
//
//   $curtail           0 for no text curtailment, or 'n' the number of
//                      characters from each post title that shoudl be
//                      displayed. e.g. Curtailing "My Dynamic Badger" to
//                      10 characters would read "My Dyna...".
//                      default = no curtailment
//
//   $showviews         true if the number of times each post has been
//                      viewed should be included in the list.
//                      default = false
//
//   $show_views_in_tt  TT is short for ToolTip setting this value to true
//                      includes the number of views as part of the tool tip.
//                      i.e. if you hover over the text the (1234 distinct
//                      viewers) message is shown.
//                      default = true
//
//   $duration          restricts the duration of the query period so that
//                      only the last £duration days are considered when
//                      measuring popularity.  e.g. a value of 30 would
//                      return the number of users only within the last
//                      30 days.  Leaving the value unset, or 0, results
//                      in the all-time results being returned.
//                      default = 0 (all-time)
//
//   $pre               this is a text string that is added to every line.
//                      default = <li>
//
//   $post              this is a text string that is added to every line.
//                      default = </li>
//   $method            there are two ways of identifying unique visitors,
//                      neither of which are perfect, the default is by
//                      recognizing only unique IP addresses, which means
//                      that if several people from one company visit, then
//                      they may show as a single user.  Alternatively,
//                      using the session_id is not perfect because some
//                      users refuse to set cookies.
//                      default="ip", alternative="session"
//   $as_percentage     if set to true, then the number of hits for each
//                      page as a percentage of the site total is displayed
//                      instead of the hit count itself.  This may be
//                      desirable if you want to show popularity without
//                      letting on how many hits you get for each story.
//                      default = false
//
//
// can be dropped into any ordered or unordered list, so for example...
//   <ul>
//   <?php MostWanted::mostwanted(); ?>
//   </ul>
//
// The example below would return a list of the top 10 entries
// with any titles longer than 30 characters trimmed to 27 in length and
// suffixed with "...".  The tooltip will still read the full title. The
// number of times the post has been viewed will be shown in brackets after
// the post title.
//   <ul>
//   <?php MostWanted::mostwanted(10, 30, true); ?>
//   </ul>
//
*/

$total_hits = -1;
$futureSpamOption "";
//$futureSpamOption = "and spam=0";

function rjb_mostwanted($top_n=5$curtail=0$showviews=false$show_views_in_tt=true$duration null$pre="<li>"$post="</li>"$method="ip"$as_percentage false) {
    
MostWanted::mostwanted($top_n$curtail$showviews$show_views_in_tt$duration$pre$post$method$as_percentage);
}

class 
MostWanted {
    
    function 
mostwanted($top_n=5$curtail=0$showviews=false$show_views_in_tt=true$duration=""$pre="<li>"$post="</li>"$method="ip"$as_percentage false){
        global 
$wpdb$tablestattraq$tableposts$user_level$ver$total_hits;
        
get_currentuserinfo();

       
$dateOption "";
        
$durationExplained "";
        if (
$duration != "") {
            
$dateOption .= "AND DATE_SUB(CURDATE(),INTERVAL $duration DAY) < st.access_time";
            
$durationExplained " in the last ".$duration." days";
        }
        if (
$method == "ip") {
            
$method="ip_address";
        } else {
            
$method="session_id";
        }

        
$distinct = ($as_percentage?" of":"")." distinct viewers";

        
$q "SELECT p.post_title, st.article_id, COUNT( DISTINCT (st.$method) ) as cnt FROM $tablestattraq st, $tableposts p where p.ID=st.article_id AND p.post_status='publish' ".$futureSpamOption." AND st.user_agent_type='0' ".$dateOption." GROUP BY st.article_id ORDER BY cnt DESC LIMIT 0,$top_n";
        
$output $wpdb->get_results$q );

        if (isset(
$output)) {
            foreach (
$output as $line) {
                if (
$showviews) {
                    
$views " ".MostWanted::getHits($as_percentage$line->cnt$dateOption)."";
                }
                if (
$show_views_in_tt) {
                    
$ttviews " (".MostWanted::getHits($as_percentage$line->cnt$dateOption).$distinct.$durationExplained.")".$append;
                }
                     
                
$short MostWanted::curtail($line->post_title$curtail) ;
                
$tstr_replace("'","&apos;"$line->post_title);
                echo 
$pre "<a title='"$t $ttviews "' href='" get_permalink($line->article_id) . "'>" . ($short) . "</a>".$post;
            }
        } else {
            
_e($pre "No results available.".$post);
        }

        
// reset the hits value so it is checked once when
        // the next page is loaded.
        
$total_hits = -1;
        return;
    }


    function 
getHits($as_percentage$count$dateOption) {
        global 
$total_hits$wpdb;
        
// start percentage lookup
        
if ($as_percentage) {
            
// get the total number of hits if it's not known already
            
if ($total_hits == -1) {
                
$q "SELECT COUNT( * ) as cnt FROM wp_stattraq st where st.user_agent_type='0'" $futureSpamOption." ".$dateOption;
                
$total_hits $wpdb->get_var$q );
            }
            return 
"" round((($count $total_hits) * 100), 1) . "%";
        } else {
            return 
$count;
        }
        
// end percentage lookup
    
}


    
// trims a message down so that it is shorter than the length
    // specified in the $trim_chars argument.
    
function curtail($trim_this$trim_chars=0) {
        if (
$trim_chars && strlen($trim_this) > $trim_chars) {
            return 
substr($trim_this,0,($trim_chars-3)) . ".";
        }
        return 
$trim_this;
    }


    
// adds a signature to the end of your page describing the 
    // version of MostWanted, which is rather handy when debugging
    // from afar.
    
function signature() {
        global 
$ver;
        
_e("<div style='display:none;visibility:hidden;'><a href='http://boakes.org/most-wanted?version=".$ver."'> </a></div>");
    }


    
// This utility method is not used by the main plugin.  It is as a
    // repair tool for stattraq data which may be incorrectly recorded
    // without an article_id, which means that the data can't show up
    // in the MostWanted output.
    //
    // If you've not hacked your stattraq plugin to fix this, then
    // a call to this method will repair all entries in your database.
    
function fixstats(){
        global 
$wpdb$tablestattraq$tableposts;
        
get_currentuserinfo();

        
// calculate duration
        
$sleep 1;
        
$output $wpdb->get_results"SELECT COUNT( DISTINCT (ID) ) as cnt FROM wp_posts;" );
        foreach (
$output as $line) {
            
$duration = ($sleep $line->cnt) /60;
        }
        
_e("<p>As a LOW_PRIORITY fix This will probably take around " $duration " minutes.  Your previous statistics are being ever-so-slightly-repaired.  Every record of a post that was accessed using a permalink is having it's post id added to it.</p><ol>");
        
$output $wpdb->get_results"SELECT id, post_name FROM wp_posts where post_status = 'publish' ORDER BY id DESC;" );

        foreach (
$output as $line) {
            
$q "UPDATE low_priority wp_stattraq SET article_id = '" $line->id "' WHERE (article_id = '0' and url like '%name=" $line->post_name "%');";
                
ob_end_flush();
            
_e("<li>Converting " $line->post_name "</li>");
            
$o2 $wpdb->get_results$q );
            
flush();
    
            
sleep($sleep);
        }
        
_e("</ol>");
       return;
    }
}

add_action('wp_footer', array('MostWanted''signature'));

// NOTE the ">" symbol in the following line must
// be the last character in the file - do not add
// any spaces, tabs or newlines after it, or you
// will get "header already sent" errors.
?>