Можно ли позволить автору сменить автора своих постов? Я понимаю, что это эффективно заблокирует их от должности, вот чего я хочу. Я хочу, чтобы они могли сменить автора после завершения редактирования.
Можно ли позволить автору сменить автора своих постов? Я понимаю, что это эффективно заблокирует их от должности, вот чего я хочу. Я хочу, чтобы они могли сменить автора после завершения редактирования.
Ответы:
Я добавляю второй ответ, потому что мой первый подход был отклонен, а этот не получил должного внимания.
Идея состоит в том, чтобы создать собственный мета-блок, который перечисляет всех пользователей и меняет автора в save_post
хуке. Таким образом, вы не вмешиваетесь в возможности пользователей, и смена автора происходит, когда сообщения уже сохранены. Также дополнительная выгода в том, что вы можете контролировать список пользователей, которые доступны в выпадающем списке авторов. Шаги, чтобы следовать:
Зарегистрировать метабокс:
function wpse313020_add_custom_box() {
// Bail out for users other than contributors
if ( ! user_can( get_current_user_id(), 'contributor' ) ) {
return;
}
// Register custom meta box
add_meta_box(
'wpse313020_author_override',
'Change Author', // metabox title
'wpse313020_author_ovveride_box_html', // callbac function
'post' // a post type you want to show the metabox on
);
}
add_action('add_meta_boxes', 'wpse313020_add_custom_box');
Создайте разметку для вашего метабокса:
/**
* HTML for custom meta box
*/
function wpse313020_author_ovveride_box_html() {
// you can modify the list of users by passing additional args to get_users()
$users = get_users();
?>
<label for="wpse313020_author_override_id">Select post author</label><br />
<select name="wpse313020_author_override_id" id="wpse313020_author_override_id" class="postbox">
<option value="">Select user...</option>
<?php
// get post ID on admin edit screen and retrieve saved post meta
$post_id = is_admin() && isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : '';
$saved_value = ! empty( $post_id ) ? get_post_meta( $post_id, 'wpse313020_author_override', true ) : '';
foreach ( $users as $user ) {
echo sprintf( '<option value="%1$d" %2$s>%3$s</option>', absint( $user->ID ), selected( $saved_value, absint($user->ID, false ) ), esc_html( $user->display_name ) );
}
?>
</select>
<?php
}
Подключитесь, save_post
чтобы сохранить данные и переопределить автора:
/**
* Save custom post meta and override the post author
*/
function wpse313020_save_postdata( $post_id ) {
if ( array_key_exists('wpse313020_author_override_id', $_POST ) ) {
// save post meta with author ID
update_post_meta( $post_id, 'wpse313020_author_override', absint( $_POST['wpse313020_author_override_id'] ) );
// now modify the post author, we need to unhook the current function to prevent infinite loop
// you could add additional check here to see if the current author is not the same as chosen author
remove_action( 'save_post', 'wpse313020_save_postdata' );
$updated_data = [
'ID' => $post_id,
'post_author' => absint( $_POST['wpse313020_author_override_id'] ),
];
wp_update_post( $updated_data );
add_action( 'save_post', 'wpse313020_save_postdata' );
}
}
add_action('save_post', 'wpse313020_save_postdata');
ПРИМЕЧАНИЕ Не
забудьте добавить поле nonce и проверить его после сохранения. Также вы можете рассмотреть возможность использования других хуков вместо save_post
, т. Е. pre_post_update
Или wp_insert_post_data
, для обработки данных при первоначальном сохранении после.
Надеюсь, это поможет!
Несмотря на то, что можно разрешить автору (или участнику) назначать другого автора для его / ее собственного поста с помощью user_has_cap
ловушки фильтра и некоторого связанного кода, однако сам этот подход в корне ошибочен . Поэтому, даже если вы примете все необходимые меры безопасности, это все равно уязвимость, потому что она все вместе разрушает архитектуру возможностей.
Позвольте мне привести пример сценария: скажем, пользователь с ролью автора имеет менее чем почетное намерение и спамит другого автора большим количеством постов (возможно, с использованием сценария). В следующий раз, когда автор назначения войдет в систему, он увидит все эти сообщения на свое имя! Это будет продолжаться, так как другой автор не может остановить это! Поэтому мы должны найти альтернативный подход, который не имеет этого недостатка.
Если смена автора является необходимой функцией, то лучшим подходом является вовлечение другого автора (или более опытного пользователя, такого как другие редакторы или администраторы) в процесс смены автора, чтобы инициатор не мог спамить автор назначения.
Чтобы достичь этого, мы позволим инициирующему автору выбрать автора назначения из редактора, но мы не будем напрямую менять автора поста. Вместо этого, во время смены автора, мы сохраним собственную мета-запись, в которой будет сохранен конечный идентификатор автора. Затем в панели администратора у нас будет подменю сообщений, в котором будут отображаться все сообщения с запросом на изменение автора. Только целевой автор и пользователи с edit_others_post
такими возможностями (например, редакторы, администраторы и т. Д.) Будут иметь доступ к этому интерфейсу запроса на изменение автора. Из пользовательского интерфейса пользователь с надлежащим доступом утвердит изменение, и только тогда произойдет окончательное изменение автора.
Реализация CODE может варьироваться в зависимости от требования, однако без какой-либо другой реализации CODE инициаторы могут изменить сообщение или даже отменить запрос на изменение автора в окне процесса утверждения. Они будут заблокированы после публикации, как только запрос на изменение автора будет утвержден.
Раскрывающийся список авторов отображается только тогда, когда у пользователя есть такая edit_others_posts
возможность. Однако по понятным причинам вы не хотите предоставлять эту возможность авторам по умолчанию. Решение состоит в том, чтобы предоставить эту возможность только при определенных обстоятельствах, а именно, когда он редактирует один из своих постов. Поскольку возможность записывается в базу данных, вы также должны убедиться, что она удалена на любой другой странице.
Это вопрос точного времени. Вы хотите изменить возможность после того, как WP решил, что автор имеет право редактировать сообщение, но до того, как post.php
будет сгенерирована форма страницы редактирования ( ). Подходящий крючок есть admin_init
.
Нравится:
add_action ('admin_init', 'wpse313020_change_author');
function wpse313020_change_author () {
global $pagenow;
$current_user = wp_get_current_user();
// only do this if current user is contributor
if ('contributor' == $current_user->roles[0]) {
// add capability when we're editing a post, remove it when we're not
if ('post.php' == $pagenow)
$current_user->add_cap('edit_others_posts')
else
$current_user->remove_cap('edit_others_posts');
}
}
Я не тестировал код, поэтому он может содержать ошибки, но вы поняли идею.
Я попытался достичь того, что вам нужно, отфильтровав метаданные участника, и это, кажется, работает нормально. Все, что я делаю здесь, это добавление edit_others_posts
возможности для участников, когда WordPress запрашивает это.
Тем не менее, я бы сказал, что это немного хакерское решение для меня, и я не уверен, что это совершенно безопасно. Судя по тому, что я проверил после установки моего фильтра в functions.php
WordPress, он не позволяет авторам редактировать сообщения других пользователей в других контекстах, кроме того, который вы просили. Это кажется нормальным, но мы не можем явно проверить, является ли текущий пользователь автором редактируемого в данный момент поста (вы не сможете сохранить пост как другого пользователя, если эта условная проверка будет добавлена в функцию) - что беспокоит меня
/**
* author_cap_filter()
*
* Filter on the current_user_can() function.
* This function is used to explicitly allow contributors to change post authors
*
* @param array $allcaps All the capabilities of the user
* @param array $cap [0] Required capability
* @param array $args [0] Requested capability
* [1] User ID
*/
function author_cap_filter( $allcaps, $cap, $args ) {
// Bail out if we're not dealing with right capability:
if ( ! in_array( $args[0], [ 'edit_others_posts' ] ) ) {
return $allcaps;
}
// Bail out for users who are not contributors
if ( ! user_can( $args[1], 'contributor' ) ) {
return $allcaps;
}
// Bail out for users who can already edit others posts:
if ( isset( $allcaps['edit_others_posts'] ) && $allcaps['edit_others_posts'] ) {
return $allcaps;
}
// overwrite 'edit_others_posts' capability
$allcaps[ $args[0] ] = true;
return $allcaps;
}
add_filter( 'user_has_cap', 'author_cap_filter', 100, 3 );
edit_others_posts
возможности по существу позволит им редактировать посты других пользователей. С таким же успехом мы можем сделать автора редактором, это, вероятно, лучше, чем дать им более высокие возможности. Второе решение возможно, но требует дополнительной работы, ИМХО.
edit_others_posts
разрешаете редактировать посты других пользователей. Пожалуйста, проверьте код из моего ответа - даже при установленном фильтре проверка возможностей if ( ! current_user_can( 'edit_post', $post_id ) )
в github.com/WordPress/WordPress/blob/… все еще возвращает false. Опять же, я согласен, что это не безопасное решение, как упомянуто в моем ответе, но я подумал, что стоит упомянуть, как оно на самом деле работает. (извините за два комментария подряд, я не соответствовал пределу харахтера)
Прежде всего, установите плагин User Role Editor ( https://wordpress.org/plugins/user-role-editor/ ).
Во-вторых, с помощью плагина создайте новую роль с именем Post Manager, например:
После создания новой роли вы сможете редактировать ее возможности. Сейчас настал момент, когда вы решили свою проблему, но вам нужно выбрать один из двух вариантов:
(пока не беспокойтесь о роли участника)
Первый:
edit_others_posts
и publish_posts
.Во-вторых:
edit_others_posts
.После принятия решения нажмите «Обновить». Ваша новая роль должна теперь иметь read
возможность плюс ту, которую вы выбрали.
Теперь перейдите на страницу профиля пользователя участника и в конце этой страницы предоставьте им дополнительные роли (функция редактора ролей пользователей):
Теперь каждый пользователь, который является Автором и Менеджером сообщений, сможет изменить автора сообщения для неопубликованных сообщений. И в зависимости от вашего предыдущего выбора пользователь может также публиковать сообщения, и если они это сделают, они больше не смогут редактировать сообщение.
ВАЖНЫЙ!!!
Я показал вам решение, создающее новую роль для сохранения стандартных возможностей Contributor. Если вы хотите (не разумно), вы можете пропустить создание Post Manager, а с помощью редактора ролей пользователей вы просто отредактируете возможности Contributor напрямую .
И просто для записи, по умолчанию WordPress позволяет только edit_others_posts
сменить автора сообщения. См. Https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/class-wp-posts-list-table.php строка 1483.