Using abs() with custom field in orderby statement

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