Show individual author rank from query of cumulative post view count for all authors

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:

Read More
<?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 🙂

Related posts

Leave a Reply

1 comment

  1. 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!";