“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'
.