How to make post sticky in the admin page?

i work with restaurant plugin that use custom post type.
the question is, if it possible to select some post and make him sticky (always be in the top) in the admin?
i need this because when you add many items to the restaurant menu, it becomes hard to find the items(posts).

so i just looking for solution to find post from post type by slug, and make him sticky in the admin page (not in the front)

i made code that find the right post, but how make him to be sticky?

        $test = get_page_by_path( 'slug', $output = OBJECT, $post_type="post-type" );
        $test_id = $test->ID;
        $test_page = get_post($test_id);
        $test_title = apply_filters('the_title', $test_page->post_title);

1 Answer
1

“Admin Stickies” for custom post types:

To support sticky custom posts in the backend, you can use the following code snippet in your functions.php file in the current theme directory or in your custom plugin:

/**
 * Set admin stickies for the 'foodmenu' custom post type 
 */
add_action( 'init', function() {
    if( function_exists( 'wpse_cpt_stickies' ) )
        wpse_cpt_stickies( $cpt="foodmenu", $ids = array( 53, 102, 23 ) );
});

where you can adjust the $cpt and $ids to your needs.

We could also create a custom meta field, e.g. is_admin_sticky for these admin sticky cpt posts. Then we can fetch them all with:

/**
 * Set admin stickies for the 'foodmenu' custom post type 
 */
add_action( 'init', function() {
    if( function_exists( 'wpse_cpt_stickies' ) )
    {
       // Fetch all sticky posts with the "is_admin_sticky=1" custom field:
       $ids = get_posts( 
           array( 
               'post_type'      => 'foodmenu', 
               'meta_key'       => 'is_admin_sticky',
               'meta_value'     => '1',
               'posts_per_page' => 5,    # <-- Modify this to your needs
           )
       ); 

    wpse_cpt_stickies( $cpt="foodmenu", $ids );
});

The “Admin Stickies” demo plugin:

We use the following plugin to support this:

<?php   
/**
 * Plugin Name:   Admin Stickies for custom post types
 * Plugin URI:    http://wordpress.stackexchange.com/a/167371/26350
 * Plugin Author: birgire
 * Version:       0.0.1
 */

function wpse_cpt_stickies( $cpt, $ids )
{
    $stickies = new WPSE_CPT_Admin_Stickies;
    $stickies->init( $cpt, $ids );
}

class WPSE_CPT_Admin_Stickies
{
    private $cpt;
    private $ids;

    public function init( $cpt="post" , $ids = array() )
    {
        $this->cpt = $cpt;
        $this->ids = $ids;
        add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
    }

    public function pre_get_posts( $q )
    {
        if( 
            is_admin() 
            && 'edit.php' === $GLOBALS['pagenow']
            && $q->is_main_query() 
            && $this->cpt === $q->get( 'post_type' )
        )
        {
            add_filter( 'post_class', array( $this, 'post_class' ), 10, 3 );    
            add_filter( 'option_sticky_posts', array( $this, 'custom_stickies' ) );
            $q->is_home = 1; # <-- We must use this "hack" to support sticky posts
            $q->set( 'ignore_sticky_posts', 0 );
        } 
    }

    public function custom_stickies( $data )
    {
        // remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
        if( count( $this->ids ) > 0 )
            $data = $this->ids;

        return $data;
    }

    public function post_class( $classes, $class, $post_ID ) 
    {
        // Append the sticky CSS class to the corresponding row:
        if( in_array( $post_ID, $this->ids, true ) )
            $classes[] = 'is-admin-sticky';

        return $classes;
    }

} // end class

The sticky posts are saved into the sticky_posts option and it’s only available for normal posts.

Here we hijack the option_sticky_posts filter to support this for custom post types in the back-end.

If we don’t remove our option_sticky_posts filter callback, after the first run, then it will also affect the is_sticky() function. Then we will get the native sticky CSS class in the table row. Therefore I’ve commented out the filter removal.

We can also use the post_class filter to add our custom is-admin-sticky CSS class to the corresponding table row.

This demo could be extended further to support the front-end, maybe with the third input parameter:

wpse_cpt_stickies( $cpt, $ids, $context );

where $context could be 'front', 'back' or 'both'.

Leave a Comment