Applying automatic order for a sort through a user function callback

Starting version 3.5.2 a new functionality has been implemented, Through a callback user function certain order can apply to a sort. This is run automatically on sort match, meaning no manual order maintenance is required. This is useful when no manual sort intend to be used due to complexity or maintenance requirement time, on automatic order fallback, a sort which can’t be achieved through existing interface functionality, etc

advanced-post-types-order-automatic-user-callback-function

The function can be included within theme function.php file or any other place / plugin which loads along with WordPress instance.

function user_custom_sorting_function($post_list, $sort_view_id, $orderBy, $query)
        {
           //custom code
                
            return $post_list;   
        }

The function parameters are:
$post_list – the list with object id
$sort_view_id – the current sort view_id
$orderBy – default orderBy
$query – current WordPress Query

Example & Case Study

Presuming there is a custom post type called Event, which is required to be sorted automatically by the “release date” which is a custom field. The sorting criteria will be the following:

  • All further to be released Events will appear on top, ascending. That means a release date of January-24 will appear before February-20
  • All released appear after previous list, ascending, meaning a released on March-10 appear before March 25

First Create simple sort for the Event Custom Post Post Type
Chose the Automatic sort type for the new sort, then enter the custom function name as show before.

function user_custom_sorting_function($post_list, $sort_view_id, $orderBy, $query)
        {
           //custom code
                
            return $post_list;   
        }

First we need to create a map list of posts along with the release date value in unixformat

//create a map list with dates in unix format
$list_timestamp_map =   array();
foreach($post_list  as  $object_id)
    {
        $_launch_date   =   get_post_meta($object_id, '_launch_date',   TRUE);
        $_launch_date   =   strtotime($_launch_date);
        
        $list_timestamp_map[$object_id]  =   $_launch_date;
    }

Sort all indexes (timestamps) ascending and create a variable which hold the today timestamp.

//sort the dates ascending
asort($list_timestamp_map);

//create a reference value as today for spiting the array
$doday  =   mktime(0,0,0, date("m"), date("d"), date("Y"));

Create a list of upcoming events

//create a list of upcomming
$upcoming_list = array();
foreach($list_timestamp_map as  $object_id  =>  $timestamp)
    {
        if($timestamp   >=  $doday)
            $upcoming_list[]    =   $object_id;
    }

Create a list of expired events

$expired_list = array();
foreach($list_timestamp_map as  $object_id  =>  $timestamp)
    {
        if(!in_array($object_id, $upcoming_list))
            $expired_list[] =   $object_id;
    }
    
$expired_list  =   array_reverse($expired_list);

Make a new array contain the upcoming and expired

$post_list  =   array_merge($upcoming_list, $expired_list);

Return the $post_list which contain the object ID’s in the order they will appear on the front side.
This is the complete code:

function user_custom_sorting_function($post_list, $sort_view_id, $orderBy, $query)
        {
            //create a map list with dates in unix format
            $list_timestamp_map =   array();
            foreach($post_list  as  $object_id)
                {
                    $_launch_date   =   get_post_meta($object_id, '_launch_date',   TRUE);
                    $_launch_date   =   strtotime($_launch_date);
                    
                    $list_timestamp_map[$object_id]  =   $_launch_date;
                }
                
            //sort the dates ascending
            asort($list_timestamp_map);
            
            //create a reference value as today for spliting the array
            $doday  =   mktime(0,0,0, date("m"), date("d"), date("Y"));
            
            //create a list of upcomming
            $upcoming_list = array();
            foreach($list_timestamp_map as  $object_id  =>  $timestamp)
                {
                    if($timestamp   >=  $doday)
                        $upcoming_list[]    =   $object_id;
                }
            
                        
            //create a list of expired
            $expired_list = array();
            foreach($list_timestamp_map as  $object_id  =>  $timestamp)
                {
                    if(!in_array($object_id, $upcoming_list))
                        $expired_list[] =   $object_id;
                }
                
            $expired_list  =   array_reverse($expired_list);
            
            $post_list  =   array_merge($upcoming_list, $expired_list);
                
            return $post_list;   
        }

This is just a simple example, but obliviously any sorting criteria can apply to achieve the order requirements.


  • Matthias

    Cool, this makes sorting much faster than using manual! Good job guys!

  • pageii

    I’ll definitely try this out on my next project!