Пользователь WordPress с пользовательской ролью не может просматривать страницу списка для пользовательских типов сообщений без возможности "create_posts" - PullRequest
2 голосов
/ 03 октября 2019

Я работаю на сайте WordPress 5.2.3 и у меня возникли проблемы с чем-то в панели администратора.

У меня есть пользовательская роль, давайте назовем ее librarian, и пользовательский тип записи, давайте назовем ееbook.

Я хочу сделать так, чтобы librarian мог редактировать book, но не создавать новый.

Следуя советам в другом вопросе (WordPress: отключите «Добавить новый» для пользовательского типа сообщения ) и WordPress документация , у меня получился следующий код:

// Custom post type.
register_post_type('book',
    array(
        'labels'                => array(
            'name' => __( 'book' ),
            'singular_name' => __( 'Book' )
        ),
        'capability_type'       => array('book', 'books'),
        'capabilities'          => array(
            'create_posts' => 'do_not_allow' // <-- The important bit.
        ),
        'map_meta_cap'          => true,
        'description'           => 'Book full of pages',
        'exclude_from_search'   => true,
        'publicly_queryable'    => false,
        'show_in_nav_menus'     => false,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'show_in_rest'          => true,
        'menu_icon'             => 'dashicons-location',
        'menu_position'         => 5,
        'supports'              => array('title', 'revisions')
    ));
// Custom role.
add_role('librarian', 'Librarian', array(
    'read'                  => true,
    'edit_books'            => true,
    'edit_published_books'  => true
));

Я ожидал, что когда я посетил edit.php?post_type=book как librariran, я бы увидел список books для редактирования, но я не увидел бы кнопку Добавить новый . Однако на самом деле я получаю ответ 403:

Извините, у вас нет доступа к этой странице.

Я думаю, что это может быть ошибка вWordPress, из-за следующих случаев:

  • Если я посещу edit.php?post_type=book как administrator, то я вижу страницу списка без кнопки Добавить новый , как требуется.
  • Если я предоставлю роли librarian возможность edit_posts, то я вижу страницу списка без кнопки Добавить новый , как требуется (но я не хочу давать имedit_posts возможность!).

Это заставляет меня думать, что это не проблема с настраиваемым типом записи в целом.

  • Если я удаляю'create_posts' => 'do_not_allow' из регистрации типа book, librarian может см. страницу списка, но она включает кнопку Добавить новый .

Это заставляет меня думать, что это не проблема с пользовательской ролью, настроенной в целом.

Кто-нибудь сталкивался с этой проблемой раньше? Я что-то пропустил из своей конфигурации? Или есть легкий патч или обходной путь?

Любая помощь будет оценена! Спасибо.

1 Ответ

2 голосов
/ 04 октября 2019

Похоже, что это ошибка в WordPress. Я нашел источник проблемы и обходной путь.

Обходной путь

Если вас не интересует причина, обходной путь - закомментировать этот бит косметического кода в wp-admin/includes/menu.php:

https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/menu.php#L168

/*
 * If there is only one submenu and it is has same destination as the parent,
 * remove the submenu.
 */
if ( ! empty( $submenu[ $data[2] ] ) && 1 == count( $submenu[ $data[2] ] ) ) {
    $subs      = $submenu[ $data[2] ];
    $first_sub = reset( $subs );
    if ( $data[2] == $first_sub[2] ) {
        unset( $submenu[ $data[2] ] );
    }
}

Это будет означать, что некоторые элементы меню, которые ранее не отображали подменю, теперь будут (с одним элементом, таким же, как элемент главного меню),но это только косметическое изменение пользовательского интерфейса.

Причина

Для тех из вас, кто хочет узнать подробности ...

При доступе к edit.php?post_type=book эта проверка не прошла в wp-admin/includes/menu.php:

https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/menu.php#L341

if ( ! user_can_access_admin_page() ) {

    /**
     * Fires when access to an admin page is denied.
     *
     * @since 2.5.0
     */
    do_action( 'admin_page_access_denied' );

    wp_die( __( 'Sorry, you are not allowed to access this page.' ), 403 );
}

Вызов на user_can_access_admin_page(), звонки на get_admin_page_parent().

Если подменю было удалено, get_admin_page_parent() возвращает пустого родителя, что в итоге приводит к ошибочному возвращению false *1036* в случае роли librarian (роль administrator проходит по другой причине).

Если подменю оставлено на месте, get_admin_page_parent() возвращает непустой родительский элемент, и проверка доступа выполняется корректно длям.

Таким образом, коренная проблема заключается в том, что глобальный $submenu используется как для определения пользовательского интерфейса, так и для принятия решений по иерархии разрешений. Я не вижу немедленного быстрого решения этой проблемы, у которого не было бы побочных эффектов где-либо еще в коде WordPress, кроме обходного пути выше.

...