/**
 * Save a visit to the post or page.
 *
 * @param WP_Post $postObject: The post being generated
 * @return null
 **/
function kp_saveVisit($postObject)
{
    global $wp_query, $kp_firstPost;
    // Check that we are on a Page or Post
    // !is_single() -- Don't save the post when we aren't on a single post page
    // !is_page() -- Don't save the post when we aren't on a single page being
    // !$kp_firstPost -- Don't save the visit after the first post in the loop
    if (!is_single() && !is_page() && !$kp_firstPost) {
        return;
    }
    // TODO: Create a better way to check if the user is visiting the post
    // Check if we want to collect statistics
    if (get_option("kp_CollectStatistics", "true") == "false") {
        return;
    }
    // If we are in test mode and if the current user is an admin, don't collect their visit data
    if (get_option("kp_AdminTestMode", "false") == "true" && kp_isUserAdmin()) {
        return;
    }
    // At this point, a non-admin user's visit will be tracked even if we are in test mode
    $kp_firstPost = false;
    // Set this to false to short circuit when kp_saveVisit is called on the next $postObject in the loop
    // Get the user's data and save the visit
    $arr = kp_getUserData();
    extract($arr);
    $recommender = new kp_recommender($ip, $ua);
    $recommender->saveVisit($wp_query->post->ID);
    return null;
}
<?php

// Load configuration, functions, and classes for the plugin
include_once "../../../../wp-load.php";
include_once "../kindred-posts-index.php";
// Check that the user is an admin
if (!kp_isUserAdmin()) {
    die("You do not have access to this page, please log in as admin");
}
// Load the test classes
include_once 'classes\\recommendedpost.php';
include_once 'classes\\recommender.php';
include_once 'classes\\renderer.php';
include_once 'classes\\test.php';
include_once 'classes\\testData.php';
include_once 'classes\\testUser.php';
include_once 'classes\\widget.php';
include_once 'classes\\plugin.php';
$testPostID = 1;
// A sample post to use for testing
$numTestsToInsert = -1;
// Set to <= 0 if you want to insert data
$testRenderer = false || isset($_GET["testAll"]) && $_GET["testAll"] == "true";
$testRecommendedPost = false || isset($_GET["testAll"]) && $_GET["testAll"] == "true";
$testRecommender = false || isset($_GET["testAll"]) && $_GET["testAll"] == "true";
$testWidget = false || isset($_GET["testAll"]) && $_GET["testAll"] == "true";
$testPlugin = false || isset($_GET["testAll"]) && $_GET["testAll"] == "true";
$testRenderer = $testRenderer || isset($_GET["testRenderer"]) && $_GET["testRenderer"] == "true";
$testRecommendedPost = $testRecommendedPost || isset($_GET["testRecommendedPost"]) && $_GET["testRecommendedPost"] == "true";
$testRecommender = $testRecommender || isset($_GET["testRecommender"]) && $_GET["testRecommender"] == "true";
$testWidget = $testWidget || isset($_GET["testWidget"]) && $_GET["testWidget"] == "true";
 /**
  * Run the recommendation engine and fill $posts with recommendedPosts objects
  *
  * @param int $numToRecommend: The number of posts to recommend
  * @param int $numClosestUsersToUse: The number of users to use when recommending posts (more is less efficient)
  * @param array<string> $recommendablePostTypes: An array of post types to recommend (if empty, recommend all post types)
  * @param bool $testModeValue: Indicates if we are in test mode and what value to look for
  * @return null
  */
 public function run($numPostsToRecommend = 5, $numClosestUsersToUse = -1, $recommendablePostTypes = array(), $testModeValue = null)
 {
     // Get the unique posts and counts for each user
     global $visitTbl, $wpdb, $defaultNumClosestUsersToUse, $maxPastUpdateDate, $trackUserAgent;
     // Check if the user is currently on a post, if not, set the current post to -1
     if (!isset($curr_post_id)) {
         $curr_post_id = -1;
         // This is so $curr_post_id can be used later
     }
     // Check if a value was passed in the function or default to the config value set in numClosestUsers
     if ($numClosestUsersToUse < 0) {
         $numClosestUsersToUse = $defaultNumClosestUsersToUse;
     }
     // Determine if we are test mode and an admin, if so, display the test mode data
     $isAdmin = kp_isUserAdmin();
     if (!isset($testModeValue)) {
         $isTestMode = get_option("kp_AdminTestMode", "false") == "true" && $isAdmin;
         if ($isTestMode) {
             $testModeValue = "1";
         } else {
             $testModeValue = "0";
         }
     }
     // Reset the recommended posts
     $this->posts = array();
     // Get the user's visit data
     if ($trackUserAgent) {
         $sql = "SELECT * FROM {$visitTbl} WHERE IP = %s AND UserAgent = %s";
         $args = array($this->ipAddress, $this->userAgent);
     } else {
         $sql = "SELECT * FROM {$visitTbl} WHERE IP = %s";
         $args = array($this->ipAddress);
     }
     $user = $wpdb->get_row($wpdb->prepare($sql, $args), OBJECT);
     $userVisits = unserialize($user->Visits);
     // Set up the closest number of users
     $closestUsers = array();
     if ($trackUserAgent) {
         $sql = "\n\t\t\t\tSELECT * \n\t\t\t\tFROM {$visitTbl} \n\t\t\t\tWHERE \n\t\t\t\t\tTestData = %s AND \n\t\t\t\t\t(IP != %s OR UserAgent != %s) AND\n\t\t\t\t\t(UpdateDate > ADDDATE(NOW(), INTERVAL %d DAY) OR CreateDate > ADDDATE(NOW(), INTERVAL %d DAY))";
         // Get the rest of the users within the past Max Update Date (ignore test mode data)
         $args = array($testModeValue, $this->ipAddress, $this->userAgent, -1 * $maxPastUpdateDate, -1 * $maxPastUpdateDate);
     } else {
         $sql = "\n\t\t\t\tSELECT * \n\t\t\t\tFROM {$visitTbl} \n\t\t\t\tWHERE \n\t\t\t\t\tTestData = %s AND \n\t\t\t\t\t(IP != %s) AND\n\t\t\t\t\t(UpdateDate > ADDDATE(NOW(), INTERVAL %d DAY) OR CreateDate > ADDDATE(NOW(), INTERVAL %d DAY))";
         // Get the rest of the users within the past Max Update Date (ignore test mode data)
         $args = array($testModeValue, $this->ipAddress, -1 * $maxPastUpdateDate, -1 * $maxPastUpdateDate);
     }
     $otherUsers = $wpdb->get_results($wpdb->prepare($sql, $args), OBJECT);
     foreach ($otherUsers as $otherUser) {
         // Get the distance between the user and the other users
         $dist = $this->getDistance($userVisits, unserialize($otherUser->Visits));
         if (count($closestUsers) < $numClosestUsersToUse) {
             array_push($closestUsers, array($otherUser->Visits, $dist));
         } else {
             // Find the max dist and replace it
             $maxDist = -1;
             $maxInd = 0;
             $i = 0;
             foreach ($closestUsers as $tempUser) {
                 if ($tempUser[1] > $maxDist && $tempUser[1] > $dist) {
                     $maxDist = $tempUser[1];
                     $maxInd = $i;
                 }
                 $i = i + 1;
             }
             // Unset that array element and push our new close user
             if ($maxDist != -1) {
                 unset($closestUsers[$maxInd]);
                 $closestUsers[$maxInd] = array($otherUser->Visits, $dist);
             }
         }
     }
     if (count($closestUsers) > 0) {
         // Get the top visit posts from the $closestUsers
         $visitCounts = array();
         // will contain {1=>5, 2=>3, 5=>150, post_id=>total visit number}
         foreach ($closestUsers as $key => $user) {
             $user[0] = unserialize($user[0]);
             foreach ($user[0] as $id => $visitCount) {
                 if (!isset($visitCounts[$id])) {
                     $visitCounts[$id] = 0;
                 }
                 $visitCounts[$id] += $visitCount;
             }
         }
         // Sort the final array by the counts
         arsort($visitCounts);
         // Build the criteria for the post types to recommend
         $preparedPostTypes = "";
         $preparedPostTypesArray = array();
         $preparedPostTypeCriteria = "";
         if (count($recommendablePostTypes) > 0) {
             foreach ($recommendablePostTypes as $postType) {
                 if ($preparedPostTypes != "") {
                     $preparedPostTypes = $preparedPostTypes . ", ";
                 }
                 $preparedPostTypes = $preparedPostTypes . "%s";
                 $preparedPostTypesArray[] = $postType;
             }
             $preparedPostTypeCriteria = " post_type IN (" . $preparedPostTypes . ") AND";
         }
         // Get a list of posts that we can recommend
         $recommendablePosts = array();
         $posts = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE {$preparedPostTypeCriteria} post_status = 'publish' AND post_parent = '0'", $preparedPostTypesArray), OBJECT);
         foreach ($posts as $post) {
             $recommendablePosts[$post->ID] = true;
         }
         // Remove certain posts if we aren't in test mode
         if (!$isTestMode) {
             // Remove the current post
             if (isset($recommendablePosts[$curr_post_id])) {
                 unset($recommendablePosts[$curr_post_id]);
             }
             // Remove posts that the user has already visited
             if ($userVisits != null && count($userVisits) > 0) {
                 foreach ($userVisits as $postId => $numVisits) {
                     if (isset($recommendablePosts[$postId])) {
                         unset($recommendablePosts[$postId]);
                     }
                 }
             }
         }
         // Recommend posts from the final list
         $i = 0;
         foreach ($visitCounts as $id => $visitCount) {
             // Check that the post isn't in the Ignore list and that we currently aren't on the post
             // If we are in test mode, we may recommend the current post
             if ($i < $numPostsToRecommend && $id != "" && isset($recommendablePosts[$id])) {
                 array_push($this->posts, new kp_recommendedPost($id));
                 $i = $i + 1;
             }
         }
     } else {
         // Need to do something
     }
     return null;
 }
 /**
  * Generates the widget html on the page
  *
  * @param Array $args: The widget arguments
  * @param Array $instance: Settings related to this instance of the Widget
  * @param boolean $outputWidgetHtml: Indicates if we should output the widget Html right away
  * @param string $template: The template to use to render the widget
  * @param Array $data: Data to use to render the widget
  * @param Array $recommendedPosts: An array of posts to display (if none, run the recommender)
  * @param string $ip: The IP Address of the user rendering the widget
  * @param string $ua: The User Agent of the user rendering the widget
  * @param bool $testModeValue: Indicates if we are in test mode and what value to look for
  * @return string: The Html for the widget
  **/
 public function widget($args, $instance, $outputWidgetHtml = true, $template = "", $data = array(), $recommendedPosts = array(), $ip = "", $ua = "", $testModeValue = null)
 {
     global $defaultNumPostsToRecommend, $kp_templates, $kp_defaultAlignment;
     // If we are in test mode and if the user isn't an admin, don't show the widget
     if (get_option("kp_AdminTestMode", "false") == "true" && !kp_isUserAdmin()) {
         return array("widgetHtml" => "", "recommender" => null);
     }
     // Check if some of the widget arguments have been passed, if not, fix them
     // so we don't run into any problems rendering the template
     if (!isset($args["before_widget"])) {
         $args["before_widget"] = "";
     }
     if (!isset($args["after_widget"])) {
         $args["after_widget"] = "";
     }
     if (!isset($args["before_title"])) {
         $args["before_title"] = "";
     }
     if (!isset($args["after_title"])) {
         $args["after_title"] = "";
     }
     if (!isset($instance["title"])) {
         $instance["title"] = "";
     }
     if (!isset($instance["featureimage"])) {
         $instance["featureimage"] = false;
     }
     if (!isset($instance["posttitle"])) {
         $instance["posttitle"] = false;
     }
     if (!isset($instance["postauthor"])) {
         $instance["postauthor"] = false;
     }
     if (!isset($instance["postdate"])) {
         $instance["postdate"] = false;
     }
     if (!isset($instance["postteaser"])) {
         $instance["postteaser"] = false;
     }
     // Get the template we are going to render
     if ($template == "" && isset($kp_templates["kp_widget"])) {
         $template = $kp_templates["kp_widget"];
     }
     // Check if the user has set the number of posts to recommend
     if (!isset($instance["numposts"]) || !is_int((int) $instance["numposts"])) {
         $numPostsToRecommend = $defaultNumPostsToRecommend;
     } else {
         $numPostsToRecommend = (int) $instance["numposts"];
     }
     // Get the different types of posts that we should recommend
     $recommendablePostTypes = array();
     $potentialRecommendablePostTypes = array();
     // Store this in case we run into no post types being set (default to everything)
     $postTypes = kp_getRecommendablePostTypes();
     foreach ($postTypes as $postType) {
         $potentialRecommendablePostTypes[] = $postType;
         // Recommend the Post Type if it is set to true within the Widget
         if (isset($instance["posttypes-" . $postType]) && (string) $instance["posttypes-" . $postType] == "1") {
             $recommendablePostTypes[] = $postType;
         }
     }
     // If we aren't recommending any type, default to all using $potentialRecommendablePostTypes
     if (count($recommendablePostTypes) == 0) {
         $recommendablePostTypes = $potentialRecommendablePostTypes;
     }
     $widgetTitle = apply_filters("widget_title", $instance["title"]);
     // Start data for this specific widget
     $alignment = $kp_defaultAlignment;
     if ($instance["alignment"] == "left") {
         $alignment = "left";
     } else {
         if ($instance["alignment"] == "right") {
             $alignment = "right";
         } else {
             if ($instance["alignment"] == "center") {
                 $alignment = "center";
             }
         }
     }
     $post_style = "padding-top:10px;padding-bottom:10px;";
     $postimage_style = "";
     $posttitle_style = "";
     $postauthor_style = "";
     $postdate_style = "";
     $postteaser_style = "";
     return kp_renderWidget($numPostsToRecommend, $recommendedPosts, $template, $ip, $ua, $outputWidgetHtml, $widgetTitle, $post_style, $postimage_style, $posttitle_style, $postauthor_style, $postdate_style, $postteaser_style, $args["before_widget"], $args["after_widget"], $args["before_title"], $args["after_title"], $alignment, $instance["featureimage"], $instance["posttitle"], $instance["postauthor"], $instance["postdate"], $instance["postteaser"], $recommendablePostTypes, $trackingCode, $testModeValue);
 }