1

I originally was going to post a question on how I would go about ranking a list of authors by the amount of post views from all of their posts combined. But I luckily found a solution here: List users with the most total posts view

This is the code I'm using from that page, except I tweaked it a little to fetch post views from a plugin I use:

<?php global $wpdb;
$topuser = array();

// query all posts by each user
$users = $wpdb->get_results("SELECT ID FROM $wpdb->users ORDER BY ID"); 
foreach ( $users as $user ) {       
    $query = get_posts( array('author' => $user->ID,  'posts_per_page' => '10000000000'));
    $counter = 0;

    // get each post of a user
    foreach ( $query as $post ){
        $views = absint( get_post_views('normal') );
        $counter += $views;
    }
    $topuser[] = array( 'id' => $user->ID, 'views' => $counter);
    wp_reset_query();
}

// function to sort array based on views count
function sortViews($a, $b) {
    return $b['views'] - $a['views'];
}
usort($topuser, 'sortViews'); // sort the array
$output = array_slice($topuser, 0, 10); // slice the array by limit 3

// output the result: user, total postview count, latest post
foreach ($output as $user){
    $profile = get_userdata($user['id']);
    $query = get_posts( array('author' => $user['id'], 'numberposts' => 1 ));

    echo '<p>' . $profile->user_nicename .' ('. $user['views'] .')</p>';            
    foreach ( $query as $post ){
        echo '<a href="' . $post->post_name . '">' . $post->post_title . '</a>';
        echo get_post_meta($post->ID, get_post_views('normal'), true);
    }
} ?>

Now I would like to take this solution a step further towards my vision when first coming up with the idea.

I want to show the specific rank (position in the list) of each user on their buddypress profile page. I would paste this code in member-header.php

Example: It would say something like "User Rank: 15", meaning that this user shows up as the 15th result when executing the above query (of course I would change the number from 10 to more which is why that would be possible).

Hope you guys can help out. Thanks in advance :)

1 Answer 1

4

First you can replace

'posts_per_page' => '10000000000'

with

'posts_per_page' => -1

to remove the limit.

If you want to show the user rank, you can add a $rank counter in the foreach loop:

$rank=0;
// output the result: user, total postview count, latest post
foreach ($output as $user){
    $rank++;
    $profile = get_userdata($user['id']);
    $query = get_posts( array('author' => $user['id'], 'numberposts' => 1 ));

    // update the rank for each user
    update_user_meta( $user['id'], 'user_rank', $rank );

    echo '<div class="user-item">';
    echo '<p>' . $profile->user_nicename .' ('. $user['views'] .') [User Rank: '.$rank.']</p>';            
    foreach ( $query as $post ){
        echo '<a href="' . $post->post_name . '">' . $post->post_title . '</a>';
        echo get_post_meta($post->ID, get_post_views('normal'), true);
    }
    echo '</div>';
}

Update:

Calculating the rank for all the users might be a job for a cron service, for example:

  1. wp-cron,
  2. linux cron,
  3. external cron service
  4. custom cron.

Here is just one idea for part 2 and 3:

  1. Create a file called mycron.php
  2. Add the two code lines at the top of the file from here: http://codex.wordpress.org/Integrating_WordPress_with_Your_Website
  3. Add your code to mycron.php
  4. Increase the array_slice limit (it's currently set to only 10)
  5. Run mycron.php to test it
  6. Add the mycron.php to a cron service (eg. daily)
  7. Add time/memory measurements to mycron.php
  8. If this gets too heavy, try to divide it to other cronjobs (maybe 500 users per cronjob)
  9. Have a large cup of coffee ;-)

ps: remember to have a backup of your database.

Update 2:

Here is an exmple of your mycron.php file, if you want to try it out in your Wordpress root folder:

<?php 

define('WP_USE_THEMES', false);
require('./wp-blog-header.php');

global $wpdb;
$topuser = array();
$html = "";

// query all posts by each user
$users = $wpdb->get_results("SELECT ID FROM $wpdb->users ORDER BY ID"); 
foreach ( $users as $user ) {       
    $query = get_posts( array('author' => $user->ID,  'posts_per_page' => -1));
    $counter = 0;

    // get each post of a user
    foreach ( $query as $post ){
        $views = absint( get_post_views('normal') );
        $counter += $views;
    }
    $topuser[] = array( 'id' => $user->ID, 'views' => $counter);
}

// function to sort array based on views count
function sortViews($a, $b) {
    return $b['views'] - $a['views'];
}
usort($topuser, 'sortViews'); // sort the array

// output the result: user, total postview count, latest post
foreach ($topuser as $user){
    $rank++;
    $profile = get_userdata($user['id']);
    $query = get_posts( array('author' => $user['id'], 'numberposts' => 1 ));

    // update the rank for each user
    update_user_meta( $user['id'], 'user_rank', $rank );

    $html .= '<div class="user-item">';
    $html .= '<p>' . $profile->user_nicename .' ('. $user['views'] .') [User Rank: '.$rank.']</p>';            
    foreach ( $query as $post ){
        $html .=  '<a href="' . $post->post_name . '">' . $post->post_title . '</a>';
        $html .=  get_post_meta($post->ID, get_post_views('normal'), true);
    }
    $html .= '</div>';
} 

echo $html;

printf(" Perfomance: %s queries in %s seconds ", get_num_queries(), timer_stop(0));

echo (file_put_contents("/path/to/ranks.html", $html)>0)? "Success!":"Problem writing to file!";
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.