Order post by taxonomy

It is quite easy to achieve this. Your answer is usort()

FEW NOTES:

Before we code, just a few notes

  • Requires PHP5.4+ due to the use of the short array syntax ([]). If you have an older version, you should really upgrade as older versions are a real security threat as all older versions prior to PHP 5.4 has been EOL’ed

  • I will comment the code as I go along so you can easy follow it

  • Taxonomy terms and custom fields are cached, so you will not be doing extra db calls, so the solution is still very lean.

  • The code below is untested, so be sure to test this locally first

THE CODE:

public function automate_posts_to_send()
{
    $value          = get_option( 'email_settings_options');
    $article_number = $value['number_of_articles_to_send'];

    /**
     * Add the tag ids here in the correct order you need your posts to be in
     * In this example, posts from tag 2 will show first, then posts from tag 3 then tag 1
     * As I said, I'm using short array syntax, so for older versions of PHP prior to 5.4,
     * [2, 3, 1] would become array( 2, 3, 1 )
     */
    $tag_order = [2, 3, 1]; 
    $args = [ 
        'tag__in' => $tag_order,
        //'orderby' => $tag_order // This is invalid ordering, add valid value here according to needs
        'posts_per_page' => $article_number,
        'date_query' => [
            [
                'after' => '24 hours ago'
            ]
        ],
    ];
    $posts_array = get_posts( $args );

    /**
     * Now we will sort the returned array of posts as we need them according to $tag_order. We will use usort()
     *
     * There is a bug in usort causing the following error:
     * usort(): Array was modified by the user comparison function
     * @see https://bugs.php.net/bug.php?id=50688
     * This bug has yet to be fixed, when, no one knows. The only workaround is to suppress the error reporting
     * by using the @ sign before usort
     */
    @usort( $posts_array, function ( $a, $b ) use ( $tag_order )
    {
        // Store our post ids in an array. We will use that to get our post tags per post
        $array = [
            'a' => $a->ID, // Use only post ID
            'b' => $b->ID // Same as above
        ];
        // Define our two variables which will hold the desired tag id
        $array_a = [];
        $array_b = [];

        // We will now get and store our post tags according to the tags in $tag_order
        foreach ( $array as $k=>$v ) {
            $tags = get_the_tags( $v );
            if ( $tags ) {
                foreach ( $tags as $tag ) {
                    if ( !in_array( $tag->term_id, $tag_order ) )
                        continue;

                    // If we found a tag that is in the $tag_order array, store it and break the foreach loop
                    ${'array_' . $k}[] = $tag->term_id; // Will produce $array_a[] = $tag->term_id or $array_b[] = $tag->term_id

                    // If we found the tag we are looking for, break the foreach loop
                    break;
                } // endforeach $tags
            } // endif $tags
        } // endforeach $array

        // Flip the $tag_order array for sorting purposes
        $flipped_tag_order = array_flip( $tag_order );

        /**
         * Lets sort our array now
         *
         * We will sort according to tag first. If the tags between two posts being compared are the same
         * we will sort the posts by post date. Adjust this as necessary
         */
        if ( $flipped_tag_order[$array_a] != $flipped_tag_order[$array_b] ) {
            return $flipped_tag_order[$array_a] - $flipped_tag_order[$array_b];
        } else {
            return $a->post_date < $b->post_date; // Change to > if you need oldest posts first
        }
    }); // end our usort ordering

    // We are done sorting, etc. Return our $posts_array
    return $posts_array;
}