Включить прикрепленные записи для произвольного типа записей
У меня есть такой произвольный тип записей: tvr_apartment
function custom_post_apartment() {
$labels = array(
'name' => 'Апартаменты',
'singular_name' => 'Апартамент',
'add_new' => 'Добавить новый',
'add_new_item' => 'Добавить новый апартамент',
'edit_item' => 'Редактировать апартамент',
'new_item' => 'Новый апартамент',
'all_items' => 'Все апартаменты',
'view_item' => 'Просмотр апартамента',
'search_items' => 'Поиск апартаментов',
'not_found' => 'Апартаменты не найдены',
'not_found_in_trash' => 'В корзине апартаменты не найдены',
'parent_item_colon' => '',
'menu_name' => 'Апартаменты'
);
$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 );
}
И я хотел бы включить функционал прикрепленных записей для него,
Я искал здесь: http://codex.wordpress.org/Function_Reference/post_type_supports
Но похоже, это не тот путь, есть какие-нибудь идеи?

Согласно обширному и длительному тикету в трекере #12702, пользовательские типы записей не поддерживают (и, вероятно, не будут поддерживать) функцию закрепления записей.
Возможно, не исключено повторно использовать эту функциональность (с огромным количеством копипаста и обработкой крайних случаев) для CPT на кастомном сайте, но, по моему мнению, кастомное решение (вероятно, на основе произвольных полей) было бы более практичным и чистым подходом.

Я использую плагин https://cs.wordpress.org/plugins/seamless-sticky-custom-post-types/

Обновление 2022:
Теперь вы можете использовать плагин, упомянутый в ответе @Ray! Протестировано и, кажется, сохраняет атрибут sticky нативным способом, так что вы можете использовать, например, ignore_sticky_posts
Оригинальный ответ:
Поскольку ни один из существующих плагинов для этой цели не поддерживает WP5, простое (но не идеальное) решение — использовать новый метабокс. В вашем плагине для CPT:
add_meta_box('pseudosticky', 'Закреплено', 'addbox', 'SLUG ВАШЕГО ПОЛЬЗОВАТЕЛЬСКОГО ТИПА ЗАПИСИ', '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"';?>> Закреплено</label>
<?
}
Затем в запросе
'meta_query' => array(
array(
'key' => 'pseudosticky',
'value' => "on",
'compare' => '='
)
//здесь можно добавить больше условий метаполей в виде массивов
),

Мне удалось заставить работать следующий подход. Позвольте описать технику, чтобы вы могли решить, использовать её или нет.
Код использует два хука: один срабатывает непосредственно перед размещением метабоксов в боковой колонке, а другой — сразу после раздела "дата/время" в метабоксе публикации.
Первый хук (до) записывает исходный тип записи, а затем меняет его на "post". WordPress считает, что это пост, и устанавливает поля по умолчанию, специфичные для типа записи "post".
Второй хук (после) восстанавливает исходный тип записи.
Если у кого-то возникнут проблемы или будут выявлены непредвиденные случаи, когда эта техника может не сработать, пожалуйста, оставьте комментарий.
// см. /wp-admin/edit-form-advanced.php .. начиная с версии wp 2.5.0
add_action( 'submitpost_box', function() {
// примечание: не получится использовать хук "post_submitbox_minor_actions" (/wp-admin/includes/meta-boxes.php), потому что $post_type устанавливается раньше
global $post;
if ( isset( $post->post_type ) && in_array( $post->post_type, array( 'post_type_1', 'post_type_2' ) ) ) {
echo 'before'; // отладка
$post->post_type_original = $post->post_type;
$post->post_type = 'post';
}
} );
// см. /wp-admin/includes/meta-boxes.php .. начиная с версии 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 'after'; // отладка
$post->post_type = $post->post_type_original;
unset( $post->post_type_original );
}
} );
Примечание: приведённый выше код добавляет опцию в интерфейс, но вам всё равно нужно будет проверять и работать с прикреплёнными записями в шаблонах/выводе — примерно как в следующем примере (но без плагина):

Для тех, кто ищет, могу подтвердить, что этот плагин работает в версии WP 5.9: https://wordpress.org/plugins/sticky-posts-switch/

Я был удивлен, обнаружив, что эта функция до сих пор недоступна.
Я надеялся, что хотя бы в WP_Query
появится что-то вроде sticky_posts
, куда можно передавать ID, но этого не случилось.
Поэтому я сделал вот так:
<?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 ); // Здесь указываем ID записей, которые должны быть закрепленными
// Также нужно показать закрепленную запись
while ( $loop->have_posts() ) : $loop->the_post();
if ( in_array($post->ID, $sticky_posts) ):
echo "Я ЗАКРЕПЛЕН!";
endif;
endwhile;
while ( $loop->have_posts() ) : $loop->the_post();
if ( !in_array($post->ID, $sticky_posts) ):
echo "Я не закреплен :( ";
endif;
endwhile;
Конечно, это не лучшее решение, у него есть несколько недостатков, но оно сработало для моей простой задачи, где нужно было закрепить только одну запись вверху.
Проблемы/Недостатки:
- Приходится модифицировать блок кода с запросами и добавлять несколько циклов.
- Нельзя настроить произвольный порядок сортировки.
- Будут отображаться только записи из текущего запроса, поэтому если закрепленная запись выходит за пределы лимита posts_per_page, она не будет закрепленной, по крайней мере на этой странице.
