Habilitar entradas fijas para post_type personalizado
Tengo este post_type personalizado: tvr_apartment
function custom_post_apartment() {
$labels = array(
'name' => 'Apartamentos',
'singular_name' => 'Apartamento',
'add_new' => 'Añadir Nuevo',
'add_new_item' => 'Añadir Nuevo Apartamento',
'edit_item' => 'Editar Apartamento',
'new_item' => 'Nuevo Apartamento',
'all_items' => 'Todos los Apartamentos',
'view_item' => 'Ver Apartamento',
'search_items' => 'Buscar Apartamentos',
'not_found' => 'No se encontraron apartamentos',
'not_found_in_trash' => 'No se encontraron apartamentos en la papelera',
'parent_item_colon' => '',
'menu_name' => 'Apartamentos'
);
$args = array(
'labels' => $labels,
'public' => true,
'query_var' => true,
'rewrite' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'taxonomies' => array('rf_apartment_feature'),
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt' )
);
register_post_type( 'tvr_apartment', $args );
}
Y me gustaría habilitar la funcionalidad de entradas fijas para el mismo,
Busqué aquí: http://codex.wordpress.org/Function_Reference/post_type_supports
Pero parece que no es la forma correcta de hacerlo, ¿alguna idea?

Según el extenso y prolongado ticket de seguimiento #12702, los tipos de entradas personalizados (CPT) no admiten (y probablemente no lo harán) la funcionalidad de posts fijos (sticky).
Probablemente no sea imposible reutilizar esta funcionalidad (con una cantidad ingente de copiar-pegar y casos extremos) para CPT en un sitio personalizado, pero en mi opinión una solución personalizada (probablemente basada en campos personalizados) sería un enfoque más práctico y limpio.

Estoy usando un plugin https://cs.wordpress.org/plugins/seamless-sticky-custom-post-types/

Edición 2022:
¡Ahora puedes usar el plugin mencionado en la respuesta de @Ray! Probado y parece guardar el atributo sticky de forma nativa, por lo que puedes usar por ejemplo ignore_sticky_posts
Respuesta Original:
Dado que ninguno de los plugins existentes para este propósito soporta WP5, una solución simple (pero no ideal) es usar un nuevo metabox. En el plugin de tu CPT:
add_meta_box('pseudosticky', 'Es sticky', 'addbox', 'TU SLUG DE TIPO DE POST PERSONALIZADO AQUÍ', 'normal', 'high');
function addbox($post, $metabox) {
$entered = get_post_meta($post->ID, 'pseudosticky', true);
?>
<label><input name="pseudosticky" type="checkbox"<?if($entered=="on")echo' checked="checked"';?>> Es sticky</label>
<?
}
Luego en la consulta
'meta_query' => array(
array(
'key' => 'pseudosticky',
'value' => "on",
'compare' => '='
)
//aquí se pueden añadir más condiciones de meta como arrays
),

He logrado que lo siguiente funcione. Permíteme describir la técnica para que puedas decidir si usarla o no.
El código utiliza dos hooks, uno que se activa justo antes de que se coloquen los meta boxes laterales y otro inmediatamente después de la sección de "fecha/hora" en el meta box de publicación.
El primer hook (antes) registra el tipo de publicación original y luego lo cambia a "post", WordPress piensa que es una entrada y establece los campos predeterminados específicos para el tipo de publicación "post".
El segundo hook (después) restablecerá el tipo de publicación al original.
Si alguien encuentra algún problema o puede identificar casos de uso no previstos donde esta técnica pueda fallar, por favor responde.
// ver /wp-admin/edit-form-advanced.php .. desde wp 2.5.0
add_action( 'submitpost_box', function() {
// nota: no se puede usar la acción "post_submitbox_minor_actions" (/wp-admin/includes/meta-boxes.php) porque $post_type se establece temprano
global $post;
if ( isset( $post->post_type ) && in_array( $post->post_type, array( 'post_type_1', 'post_type_2' ) ) ) {
echo 'antes'; // depuración
$post->post_type_original = $post->post_type;
$post->post_type = 'post';
}
} );
// ver /wp-admin/includes/meta-boxes.php .. desde wp 2.9.0
add_action( 'post_submitbox_misc_actions', function() {
global $post;
if ( isset( $post->post_type_original ) && in_array( $post->post_type_original, array( 'post_type_1', 'post_type_2' ) ) ) {
echo 'después'; // depuración
$post->post_type = $post->post_type_original;
unset( $post->post_type_original );
}
} );
Nota: lo anterior se encarga de agregar la opción a la interfaz de usuario, aún necesitarías verificar y trabajar con publicaciones fijas (sticky posts) en tus plantillas/salida... algo como lo siguiente (pero sin el plugin):

Para aquellos que estén buscando, puedo confirmar que este plugin funciona en la versión 5.9 de WordPress: https://wordpress.org/plugins/sticky-posts-switch/

Me sorprendió descubrir que esta característica todavía no está disponible.
Esperaba que al menos en WP_Query
pudiéramos obtener algo como sticky_posts
donde pasar los IDs, pero no existía.
Así que hice algo como esto:
<?php
$args = array( 'post_type' => 'some_post_type', 'posts_per_page' => 20 , 'orderby' => 'title', 'order' => 'ASC');
$loop = new WP_Query( $args );
$sticky_posts = array( 11462 ); // aquí van los IDs de los posts que quieres hacer sticky
// También necesitamos mostrar los sticky
while ( $loop->have_posts() ) : $loop->the_post();
if ( in_array($post->ID, $sticky_posts) ):
echo "¡Soy STICKY!";
endif;
endwhile;
while ( $loop->have_posts() ) : $loop->the_post();
if ( !in_array($post->ID, $sticky_posts) ):
echo "No soy sticky :( ";
endif;
endwhile;
Por supuesto esta no es la mejor solución, tiene varias limitaciones, pero funcionó para mi requerimiento simple donde solo tenía un post que quería fijar arriba.
Problemas/Limitaciones:
- Tienes que modificar el bloque de código donde tienes las consultas y añadir múltiples bucles.
- No puedes ordenarlos de forma personalizada.
- Solo los posts en la consulta actual se mostrarán, así que si tienes un post sticky más allá del límite de posts por página, ese post no será sticky, al menos en esa página.
