Разрешить Участнику сменить автора своего поста?

9

Можно ли позволить автору сменить автора своих постов? Я понимаю, что это эффективно заблокирует их от должности, вот чего я хочу. Я хочу, чтобы они могли сменить автора после завершения редактирования.

Майкл Роджерс
источник
Просто интересно здесь, есть ли другой способ для достижения бизнес-потребностей. Предоставление не редактору / администратору возможности назначать любому другому автору их пост кажется немного широким. Существует ли заранее определенный список авторов, которых они могут назначить «автором»? Есть ли определенная связь между автором и разрешенными авторами? Или они могут выбрать любого автора, который им нравится?
Анмари
Также отмечу, что это не будет «публиковать» их пост. Поэтому звучит так, как будто мы хотим имитировать какой-то рабочий процесс, в котором вкладчик назначает сообщение автору, а не говорит редактору, выбирающему «ожидающие рассмотрения» сообщения для проверки. Если ваши авторы могут быть редакторами, то, возможно, используйте wp как есть и, возможно, используйте теги, чтобы общаться или выделять, какие редакторы должны выбрать какие сообщения?
Анмари
Ах, вы говорите: «Заблокируйте их с поста, вот чего я хочу». Это важнее? Что после того, как они «отправят на проверку», они больше не смогут редактировать? Нужно ли связываться с «авторами»? Или какой-нибудь непубличный статус сработает? Может быть, используя codex.wordpress.org/Post_Status#Custom_Status
anmari

Ответы:

1

Я добавляю второй ответ, потому что мой первый подход был отклонен, а этот не получил должного внимания.

Идея состоит в том, чтобы создать собственный мета-блок, который перечисляет всех пользователей и меняет автора в 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, для обработки данных при первоначальном сохранении после.

Надеюсь, это поможет!

Леви Дульштейн
источник
1

Ловушки:

Несмотря на то, что можно разрешить автору (или участнику) назначать другого автора для его / ее собственного поста с помощью user_has_capловушки фильтра и некоторого связанного кода, однако сам этот подход в корне ошибочен . Поэтому, даже если вы примете все необходимые меры безопасности, это все равно уязвимость, потому что она все вместе разрушает архитектуру возможностей.

Позвольте мне привести пример сценария: скажем, пользователь с ролью автора имеет менее чем почетное намерение и спамит другого автора большим количеством постов (возможно, с использованием сценария). В следующий раз, когда автор назначения войдет в систему, он увидит все эти сообщения на свое имя! Это будет продолжаться, так как другой автор не может остановить это! Поэтому мы должны найти альтернативный подход, который не имеет этого недостатка.

Лучший подход:

Если смена автора является необходимой функцией, то лучшим подходом является вовлечение другого автора (или более опытного пользователя, такого как другие редакторы или администраторы) в процесс смены автора, чтобы инициатор не мог спамить автор назначения.

Чтобы достичь этого, мы позволим инициирующему автору выбрать автора назначения из редактора, но мы не будем напрямую менять автора поста. Вместо этого, во время смены автора, мы сохраним собственную мета-запись, в которой будет сохранен конечный идентификатор автора. Затем в панели администратора у нас будет подменю сообщений, в котором будут отображаться все сообщения с запросом на изменение автора. Только целевой автор и пользователи с edit_others_postтакими возможностями (например, редакторы, администраторы и т. Д.) Будут иметь доступ к этому интерфейсу запроса на изменение автора. Из пользовательского интерфейса пользователь с надлежащим доступом утвердит изменение, и только тогда произойдет окончательное изменение автора.

Что происходит с сообщениями в очереди на утверждение?

Реализация CODE может варьироваться в зависимости от требования, однако без какой-либо другой реализации CODE инициаторы могут изменить сообщение или даже отменить запрос на изменение автора в окне процесса утверждения. Они будут заблокированы после публикации, как только запрос на изменение автора будет утвержден.

Fayaz
источник
0

Раскрывающийся список авторов отображается только тогда, когда у пользователя есть такая 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');
    }
  }

Я не тестировал код, поэтому он может содержать ошибки, но вы поняли идею.

cjbj
источник
-1

Я попытался достичь того, что вам нужно, отфильтровав метаданные участника, и это, кажется, работает нормально. Все, что я делаю здесь, это добавление edit_others_postsвозможности для участников, когда WordPress запрашивает это.

Тем не менее, я бы сказал, что это немного хакерское решение для меня, и я не уверен, что это совершенно безопасно. Судя по тому, что я проверил после установки моего фильтра в functions.phpWordPress, он не позволяет авторам редактировать сообщения других пользователей в других контекстах, кроме того, который вы просили. Это кажется нормальным, но мы не можем явно проверить, является ли текущий пользователь автором редактируемого в данный момент поста (вы не сможете сохранить пост как другого пользователя, если эта условная проверка будет добавлена ​​в функцию) - что беспокоит меня

/**
 * 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 );
Леви Дульштейн
источник
2
Обратите внимание, что предоставление авторам edit_others_postsвозможности по существу позволит им редактировать посты других пользователей. С таким же успехом мы можем сделать автора редактором, это, вероятно, лучше, чем дать им более высокие возможности. Второе решение возможно, но требует дополнительной работы, ИМХО.
Скотт
Я чувствую, что отрицательное голосование здесь несправедливо, я фактически указываю на обе вещи в своем ответе, утверждая, что первое решение небезопасно, и отмечаю, что второе решение требует дополнительной работы, но я считаю, что это полезно, поскольку оно показывает работающее решение. что OP может улучшиться (я не думаю, что ответ на вопрос по WPSE должен означать предоставление готовых фрагментов кода). Кроме того, было бы полезно, если бы вы могли быть более точными и указать, что можно улучшить, или даже отредактировать мой пост, если вы имеете в виду небольшие изменения. Ура!
Леви Дульштайн
Кроме того, вы не совсем правы, когда edit_others_postsразрешаете редактировать посты других пользователей. Пожалуйста, проверьте код из моего ответа - даже при установленном фильтре проверка возможностей if ( ! current_user_can( 'edit_post', $post_id ) )в github.com/WordPress/WordPress/blob/… все еще возвращает false. Опять же, я согласен, что это не безопасное решение, как упомянуто в моем ответе, но я подумал, что стоит упомянуть, как оно на самом деле работает. (извините за два комментария подряд, я не соответствовал пределу харахтера)
Леви Дульштайн
-2

Прежде всего, установите плагин 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.

filipecsweb
источник
1
это делает пользователя редактором, для этого не нужно устанавливать плагины, просто используйте пользователя admin. Во всяком случае, это не то, что просит ОП.
Марк Каплун
Это решение явно позволяет Участнику сменить автора сообщения. Так что, да, это то, что он просил. Во-вторых, по умолчанию редактору назначено более 20 возможностей. Мое решение не делает Contributor редактором. Пусть тот, кто спросил, решит, если мой ответ решит их проблему. Пожалуйста, подумайте дважды о своем понижении.
filipecsweb
ОП просит, чтобы участник сделал что-то. Ваше решение состоит в том, чтобы сделать его редактором, который может менять авторов каждый раз, когда нарушает безопасность
Марк Каплун