Как добавить "Закрепить запись на главной" в интерфейсе сайта?
У меня есть сайт про бейсбол с несколькими авторами. Я использую функцию "Закрепить запись на главной" для обозначения "Выбора редактора" в статьях. Я хотел бы добавить ссылку/кнопку, позволяющую редакторам делать это прямо из интерфейса сайта. Метод может быть реализован либо в самой статье, либо в админ-баре. У меня нет особых предпочтений.
Я просмотрел множество плагинов для админ-бара, но не смог найти ничего связанного с функцией "Закрепить запись на главной".
Спасибо

Есть несколько полезных функций, которые пригодятся здесь:
unstick_post
- Открепить записьstick_post
- Закрепить записьis_sticky
- Проверить, является ли запись закрепленной
Имея эти три функции, все, что нам нужно сделать, это объединить их с помощью панели администратора.
Для начала давайте обернем все в класс для удобства и гибкости. Этот класс будет содержать несколько констант, которые мы будем использовать позже: nonce, действие для открепления записи и действие для закрепления записи.
class WPSE_58818_Stick_Post
{
/**
* Ajax nonce.
*
* @since 1.0
*/
const NONCE = 'wpse58818_nonce_';
/**
* Действие открепления через Ajax
*
* @since 1.0
*/
const UNSTICK = 'wpse58818_unstick';
/**
* Действие закрепления через Ajax
*
* @since 1.0
*/
const STICK = 'wpse58818_stick';
} // конец класса
Теперь добавим функцию init для добавления наших действий. Первое действие - это подключение к template_redirect.
<?php
class WPSE_58818_Stick_Post
{
// пропущено
/**
* Добавляет действия и прочее.
*
* @since 1.0
* @access public
* @uses add_action
*/
public static function init()
{
add_action(
'template_redirect',
array(__CLASS__, 'template_r')
);
}
}
ПРИМЕЧАНИЕ: далее я буду опускать часть с class
. Полную версию можно посмотреть здесь.
В функции, подключенной к template_redirect
, мы проверим, находимся ли мы на странице отдельной записи и может ли пользователь ее редактировать. Если да, то подключимся к admin_bar_menu
и wp_footer
.
/**
* Подключено к `template_redirect`. Добавляет кнопку закрепления/открепления
* в панели администратора, если мы находимся на странице отдельной записи
* и текущий пользователь может редактировать запись
*
* @since 1.0
* @access public
* @uses add_action
*/
public static function template_r()
{
if(
!is_single() ||
!current_user_can('edit_post', get_queried_object_id())
) return; // не отдельная запись или пользователь не может ее редактировать
// Подключаемся к admin_bar_menu для добавления элементов
add_action(
'admin_bar_menu',
array(__CLASS__, 'menu'),
100
);
// Подключаемся к подвалу и выводим JavaScript
add_action(
'wp_footer',
array(__CLASS__, 'footer')
);
}
В функции menu
, подключенной к admin_bar_menu
, мы можем добавить наш новый элемент:
/**
* Подключено к `admin_bar_menu`. Добавляет наш узел закрепления/открепления.
*
* @since 1.0
* @access public
*/
public static function menu($mb)
{
// получаем ID текущей записи
$post_id = get_queried_object_id();
$mb->add_node(array(
'id' => 'wpse58818-sticker',
'meta' => array(
'class' => 'wpse58818-sticker',
'title' => is_sticky($post_id) ? 'unstick' : 'stick'
),
'title' => is_sticky($post_id) ? __('Открепить') : __('Закрепить'),
'href' => self::get_url($post_id)
));
}
Здесь у нас появляется первая "вспомогательная функция", которая строит URL для узла панели администратора. Это просто обертка вокруг add_query_arg
для добавления nonce и создания URL, который мы будем использовать с AJAX позже:
/**
* Получаем URL для Ajax запроса для указанной записи
*
* @since 1.0
* @access protected
*/
protected static function get_url($post_id)
{
return add_query_arg(array(
'post_id' => absint($post_id),
'action' => is_sticky($post_id) ? self::UNSTICK : self::STICK,
'nonce' => wp_create_nonce(self::NONCE . $post_id)
), admin_url('admin-ajax.php'));
}
Функция footer
просто выводит JavaScript для выполнения AJAX запросов. Основная идея: при клике на нашу новую ссылку делаем GET запрос по указанному URL. Если запрос успешен, меняем href, текст и title ссылки (от)крепления.
/**
* Подключено к `wp_footer`. Выводит немного JS для закрепления/открепления записи
*
* @since 1.0
* @access public
*/
public static function footer()
{
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.wpse58818-sticker a').on('click', function(e) {
e.preventDefault();
var action = $(this).attr('title');
var that = this;
$.get(
$(this).attr('href'),
{},
function(data) {
if('0' == data)
{
console.log(data);
alert('<?php echo esc_js(__('Произошла ошибка')); ?>');
return;
}
$(that).attr('href', data);
if('stick' == action) {
$(that).html('<?php echo esc_js(__('Открепить')); ?>');
$(that).attr('title', 'unstick');
} else {
$(that).html('<?php echo esc_js(__('Закрепить')); ?>');
$(that).attr('title', 'stick');
}
}
);
});
});
</script>
<?php
}
Теперь перейдем к AJAX обработчикам. Ajax в плагинах/темах стоит изучить подробнее.
Немного модифицируем нашу функцию init
, добавив два новых действия:
/**
* Добавляет действия и прочее.
*
* @since 1.0
* @access public
* @uses add_action
*/
public static function init()
{
add_action(
'template_redirect',
array(__CLASS__, 'template_r')
);
// Ajax действия
add_action(
'wp_ajax_' . self::STICK,
array(__CLASS__, 'stick')
);
add_action(
'wp_ajax_' . self::UNSTICK,
array(__CLASS__, 'unstick')
);
}
И наши AJAX обработчики. Они вполне могли бы быть одной функцией. Я разделил их здесь, так как это упрощает возможное расширение/изменение в будущем. Обе этих функции проверяют валидность AJAX запроса, (от)крепляют запись соответствующим образом и выводят новый URL для будущих (от)креплений.
/**
* Ajax обработчик для функции закрепления
*
* @since 1.0
* @access public
*/
public static function stick()
{
$post_id = self::can_ajax();
stick_post($post_id);
echo self::get_url($post_id);
die();
}
/**
* Ajax обработчик для функции открепления
*
* @since 1.0
* @access public
* @uses unstick_post
*/
public static function unstick()
{
$post_id = self::can_ajax();
// nonces проверены, все готово к откреплению!
unstick_post($post_id);
echo self::get_url($post_id);
die();
}
Здесь появляется наша вторая "вспомогательная функция". can_ajax
проверяет наши nonces и права пользователя, возвращая ID записи для (от)крепления. Если какие-либо проверки не пройдены, функция завершает выполнение (через die('1')
).
/**
* Проверяет, может ли текущий пользователь выполнять Ajax запросы. Возвращает ID записи
* для закрепления/открепления в случае успеха. В противном случае завершает выполнение.
*
* @since 1.0
* @access protected
*/
protected static function can_ajax()
{
$post_id = isset($_REQUEST['post_id']) ? $_REQUEST['post_id'] : '';
if(
!$post_id ||
!check_ajax_referer(self::NONCE . $post_id, 'nonce', false)
) die('0');
if(!current_user_can('edit_post', $post_id))
die('0');
return $post_id;
}
Вот вся эта конструкция в виде плагина.

Получаю эту ошибку при загрузке .php файла плагина через WordPress. The package could not be installed. PCLZIP_ERR_BAD_FORMAT (-10) : Unable to find End of Central Dir Record signature

Тогда загрузи через FTP и отпиши? Скорее всего, потому что плагин не в своей папке или что-то в этом роде.

Я добавил файл .php в папку, затем запаковал папку в .zip. Загрузил плагин через WordPress. Все загрузилось и установилось. Кнопка "Stick" отображается в админ-баре, но при нажатии появляется ошибка с текстом - "Произошла ошибка". Я использую Google Chrome, если это имеет значение.

Это означает, что что-то пошло не так в ajax-запросе. Либо неверный nonce, ID поста или проблемы с правами. Без доступа к вашему сайту (что я не собираюсь делать) я не могу помочь — у меня на локальной машине всё работает. Шаг 1: работает ли это с темой по умолчанию? Могут ли другие плагины вызывать проблемы?

На моей стороне закрепление и открепление работает нормально, но страница не обновляется (WP 3.4.1, плагины отключены, TwentyTen без изменений). Процесс зависает в Ajax-запросе, скриншот: http://cl.ly/IOo8 . . . . . +1+ Очень хорошая работа, профессионально сделано :)

Я думаю, этот небольшой исходный код - ваше решение. В настоящее время он не имеет обратной связи на фронтенде для изменения Sticky Post, но вы можете улучшить эту строку, класс или что угодно в функции fb_stick_post
.
Первая функция добавляет элемент в панель администратора и создает новый URL с параметром. Также при on click
вызывается функция для чтения параметра URL, и если он истинный, то изменяется sticky статус этого ID записи.
add_action( 'admin_bar_menu', 'fb_add_admin_bar_sticky', 35 );
function fb_add_admin_bar_sticky() {
global $wp_admin_bar;
if ( ! is_super_admin() || ! is_admin_bar_showing() )
return;
$current_object = get_queried_object();
if ( empty($current_object) )
return;
if ( ! empty( $current_object->post_type ) &&
( $post_type_object = get_post_type_object( $current_object->post_type ) ) &&
current_user_can( $post_type_object->cap->edit_post, $current_object->ID )
) {
$wp_admin_bar->add_menu(
array(
'id' => 'sticky_post',
'title' => __('Sticky'),
'href' => get_permalink() . '?stick_post=true',
'meta' => array(
'title' => __( 'Click me' ),
'onclick' => fb_stick_post( get_the_ID() )
)
)
);
}
}
function fb_stick_post( $post_id ) {
if ( isset($_GET['stick_post']) && 'true' == htmlspecialchars( $_GET['stick_post'] ) )
stick_post( $post_id );
}
Обновление 30.07.2012
Теперь небольшой плагин с простым решением. Плагин добавляет элемент в панель администратора. Текст кнопки проверяет, является ли запись sticky, и дает возможность сделать её sticky или unsticky.
Я изменил хук для добавления элемента в панель администратора на `template_redirect`, чтобы использовать перенаправление после обновления sticky статуса записи.
<?php
/**
* Plugin Name: Stick/Unstick post via Admin bar
*
*/
if ( ! function_exists( 'fb_add_admin_bar_sticky' ) ) {
add_action( 'template_redirect', 'fb_add_admin_bar_sticky' );
function fb_add_admin_bar_sticky() {
global $wp_admin_bar;
if ( ! is_super_admin() || ! is_admin_bar_showing() )
return;
$current_object = get_queried_object();
if ( empty($current_object) )
return;
if ( ! empty( $current_object->post_type ) &&
( $post_type_object = get_post_type_object( $current_object->post_type ) ) &&
current_user_can( $post_type_object->cap->edit_post, $current_object->ID )
) {
// проверяем, является ли запись sticky
if ( is_sticky( get_the_ID() ) ) {
$title = __('Unsticky');
$link = '?unstick_post=true';
$attr_title = __( 'Make this post unsticky' );
} else {
$title = __('Sticky');
$link = '?stick_post=true';
$attr_title = __( 'Make this post sticky' );
}
$wp_admin_bar->add_menu(
array(
'id' => 'sticky_post',
'title' => $title,
'href' => get_permalink() . $link,
'meta' => array(
'title' => $attr_title,
'onclick' => fb_stick_post( get_the_ID() )
)
)
);
}
}
function fb_stick_post( $post_id ) {
if ( isset($_GET['stick_post']) && 'true' == htmlspecialchars( $_GET['stick_post'] ) ) {
stick_post( $post_id );
wp_redirect( get_permalink( $post_id ) );
exit();
}
if ( isset($_GET['unstick_post']) && 'true' == htmlspecialchars( $_GET['unstick_post'] ) ) {
unstick_post( $post_id );
wp_redirect( get_permalink( $post_id ) );
exit();
}
}
}
или скачайте этот плагин Gist 3214922

Небольшой исходный код (и элегантный) работает из коробки, мне только не хватает функции Unstick, но опять же: этого и не просили!

Да, я тоже так думаю; но этого не было в вопросе. Это также возможно через url-параметр и функцию unstick( $post_id )
. Также мне не хватает визуальной обратной связи при изменении sticky-статуса.

Добро пожаловать! Теперь также доступен плагин для скачивания на Gist 3214922

Вот гораздо более простое решение, которое выполнит задачу с использованием хука фильтра the_content
add_filter('the_content','simplest_sticky_solution');
function simplest_sticky_solution($content){
global $post;
//ранний выход, если не требуется
if (!is_single() || !current_user_can('edit_post',$post->ID))
return $content;
//проверяем, отправлена ли форма, и действуем соответствующим образом
if (isset($_POST['sticky_action']) && isset($_POST['sticky_id']) && isset($_POST['sticky_nonce']) && wp_verify_nonce($_POST['sticky_nonce'], 'StickIt')){
if (is_sticky($post->ID)){
stick_post($post->ID);
}else{
unstick_post($post->ID);
}
}
//создаем форму
$label = (is_sticky())? "Открепить": "Закрепить";
$form = '
<form action="" method="POST">
<input type="hidden" name="sticky_id" value="'.$post->id.'">
<input type="hidden" name="sticky_action" value="stickit">
<input type="hidden" name="sticky_nonce" value="'.wp_create_nonce('StickIt').'">
<input type="button" name="submit" value="'.$label.'">
</form>';
return $form.'<br/>'.$content;
}

Я получаю эту ошибку Parse error: syntax error, unexpected T_RETURN in /home1/travisp2/public_html/crowncrazed/wp-content/themes/qawker/functions.php on line 7
которая указывает на return $content;
