Custom Class to do the custom parse
class AS_Query extends \WP_Query {
protected function parse_orderby($order_by) {
$additional_allowed = array();
$absValue = null;
if (preg_match('/abs\(([0-9]+)\)/i', $order_by, $matches)) {
$absValue = $matches[1];
$order_by = sprintf('abs((meta_value+0) - %s)', intval($matches[1]));
$additional_allowed[] = $order_by;
}
if (!in_array($order_by, $additional_allowed, true)) {
$parent_orderby = parent::parse_orderby($order_by);
if ($parent_orderby) {
return $parent_orderby;
}
return false;
}
return $order_by;
}
protected function parse_order($order) {
if (!is_string($order) || empty($order)) {
return 'DESC';
}
if ('ABS' == strtoupper($order)) {
return ''; // to get the real closest order, this should be empty
} else if ('ASC' === strtoupper($order)) {
return 'ASC';
} else {
return 'DESC';
}
}
}
Usage:
$order= get_field("custom_post_order");
$id = get_the_ID(); //to not show the post itself in the list
if (!empty($order)) {
require_once get_template_directory() . "/functions/classes/class-as-query.php";
$diretoria = new AS_Query(
array(
'order' => 'abs', // to remove "DESC" in the query to get the abs list
'orderby' => 'abs(' . $order. ')',
'meta_key' => 'custom_post_order',
'posts_per_page' => 4, //custom list limit
'post__not_in' => array($id), //to not show the post itself in the list
'post_type' => 'ordered_post'
)
);
}
I haven’t tested it with arrays of order_by