Last active
December 6, 2022 09:01
-
-
Save 19h47/c54fd0e7a5c6fbc99a6087e7606054c0 to your computer and use it in GitHub Desktop.
WP Sticky Custom Post Types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: WP Sticky Custom Post Types | |
* Plugin URI: https://gist.github.com/19h47/c54fd0e7a5c6fbc99a6087e7606054c0 | |
* Description: WP Sticky Custom Post Types is a plugin that enables support for sticky custom post types. | |
* Version: 0.0.1 | |
* Author: Jérémy Levron | |
* Author URI: https://19h47.fr | |
* | |
* @package WordPress | |
* @subpackage WP_Sticky_Custom_Post_Types | |
*/ | |
if ( ! function_exists( 'wp_sticky_custom_post_types' ) ) { | |
add_action( 'init', 'wp_sticky_custom_post_types', 20 ); | |
/** | |
* WP Sticky Custom Post Types | |
* | |
* @return void | |
*/ | |
function wp_sticky_custom_post_types() : void { | |
$post_types = get_custom_post_types(); | |
foreach ( $post_types as $post_type ) { | |
add_action( 'save_post_' . $post_type->name, 'stick_custom_post', 10, 2 ); | |
} | |
/** | |
* Post states | |
* | |
* @param string[] $post_states An array of post display states. | |
* @param WP_Post $post The current post object. | |
* | |
* @return array $states | |
*/ | |
add_filter( | |
'display_post_states', | |
function( array $post_states, WP_Post $post ) use ( $post_types ) { | |
foreach ( $post_types as $post_type ) { | |
if ( is_sticky_post_type( $post->ID, $post_type->name ) ) { | |
$post_states[] = __( 'Sticky', 'wpstickycustomposttype' ); | |
} | |
} | |
return $post_states; | |
}, | |
10, | |
2 | |
); | |
} | |
/** | |
* Get custom post types | |
* | |
* @see https://developer.wordpress.org/reference/functions/get_post_types/ | |
* | |
* @return string[]|WP_Post_Type[] An array of post type names or objects. | |
*/ | |
function get_custom_post_types() { | |
$args = array( | |
'public' => true, | |
'_builtin' => false, | |
); | |
return get_post_types( $args, 'objects' ); | |
} | |
/** | |
* Make a custom post sticky. | |
* | |
* @param int $post_ID Post ID. | |
* @param WP_Post $post Post object. | |
* | |
* @return bool True if the post was stick, false otherwise. | |
*/ | |
function stick_custom_post( int $post_ID, WP_Post $post ) : bool { | |
$post_type = get_post_type_object( $post->post_type ); | |
$name = to_snake_case( $post_type->label ); | |
$stickies = get_option( 'sticky_' . $name ) ? get_option( 'sticky_' . $name ) : array(); | |
if ( ! in_array( $post_ID, $stickies, true ) && ( isset( $_POST[ "sticky_$post->post_type" ] ) && ! empty( $_POST[ "sticky_$post->post_type" ] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
array_unshift( $stickies, $post_ID ); | |
return update_option( "sticky_$name", array_values( $stickies ) ); | |
} | |
if ( in_array( $post_ID, $stickies, true ) && ! isset( $_POST[ "sticky_$post->post_type" ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
$key = array_search( $post_ID, $stickies, true ); | |
unset( $stickies[ $key ] ); | |
return update_option( "sticky_$name", array_values( $stickies ) ); | |
} | |
return false; | |
} | |
add_action( 'post_submitbox_minor_actions', 'post_submitbox_minor_actions', 10, 1 ); | |
/** | |
* Post submitbox minor actions | |
* | |
* @param WP_Post $post WP_Post object for the current post. | |
* | |
* @see https://developer.wordpress.org/reference/hooks/post_submitbox_minor_actions/ | |
*/ | |
function post_submitbox_minor_actions( WP_Post $post ) : void { | |
$post_type = get_post_type_object( $post->post_type ); | |
if ( false === $post_type->_builtin ) { | |
ob_start(); | |
} | |
} | |
add_action( 'post_submitbox_misc_actions', 'post_submitbox_misc_actions', 10, 1 ); | |
/** | |
* Post submitbox misc actions | |
* | |
* @param WP_Post $post WP_Post object for the current post. | |
* | |
* @see https://developer.wordpress.org/reference/hooks/post_submitbox_misc_actions/ | |
* | |
* @return void | |
*/ | |
function post_submitbox_misc_actions( WP_Post $post ) : void { | |
$post_type = get_post_type_object( $post->post_type ); | |
if ( false === $post_type->_builtin ) { | |
$temp = ob_get_clean(); | |
// WP core need two different checkbox: on for authors, and another one for editors. | |
$sticky_box = '<input type="checkbox" style="display:none" name="hidden_post_sticky" id="hidden-post-sticky" value="sticky" ' . checked( is_sticky_post_type( $post->ID, $post->post_type ), true, false ) . ' />'; | |
if ( current_user_can( 'edit_others_posts' ) ) { | |
$sticky_box .= sprintf( | |
'<span id="sticky-span"><input id="super-sticky" name="sticky_' . $post->post_type . '" type="checkbox" value="sticky" %1$s /><label for="super-sticky" class="selectit">%2$s</label><br/></span>', | |
checked( is_sticky_post_type( $post->ID, $post->post_type ), true, false ), | |
__( 'Stick this post to the front page' ) | |
); | |
} | |
$pattern = '/(<input.*id="visibility-radio-password")/U'; | |
$output = preg_replace( $pattern, "{$sticky_box}$1", $temp ); | |
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
} | |
} | |
/** | |
* To snake case | |
* | |
* @param string $input Input string. | |
*/ | |
function to_snake_case( $input ) { | |
$pattern = '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!'; | |
preg_match_all( $pattern, $input, $matches ); | |
$ret = $matches[0]; | |
foreach ( $ret as &$match ) { | |
$match = strtoupper( $match ) === $match ? strtolower( $match ) : lcfirst( $match ); | |
} | |
return implode( '_', $ret ); | |
} | |
/** | |
* Is sticky post type | |
* | |
* Check if a post type is sticky | |
* | |
* @param int $post_id Post ID. | |
* @param string $post_type Post type. | |
*/ | |
function is_sticky_post_type( int $post_id, string $post_type ) { | |
$name = to_snake_case( ( get_post_type_object( $post_type ) )->label ); | |
$stickies = get_option( "sticky_$name" ); | |
$is_sticky = false; | |
if ( is_array( $stickies ) ) { | |
$stickies = array_map( 'intval', $stickies ); | |
$is_sticky = in_array( $post_id, $stickies, true ); | |
} | |
/** | |
* Filter wheter a custom post is sticky | |
* | |
* @param bool $is_sticky Whether a post is sticky. | |
* @param int $post_id Post ID. | |
*/ | |
return apply_filters( "is_sticky_$name", $is_sticky, $post_id ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment