Поддержка Проблемы и решения Не работает remove_cap

  • Решено icopydoc

    (@icopydoc)


    Столкнулся с неожиданной траблой. Не могу урезать конкретного юзера в правах.

    $cur_user_id = get_current_user_id(); // id текущего юзера
    $user = new WP_User( $cur_user_id ); // создаем экземпляр касса юзера
    $user->remove_cap( 'publish_posts' ); // и урезаем права
    if(current_user_can('publish_posts') ){
    echo "У юзера есть право publish_posts!";
    }

    Код возвращает мне «У юзера есть право publish_posts!» хотя оно ж блин строкой ранее было удалено по идее… В чем может быть трабла?

Просмотр 7 ответов — с 1 по 7 (всего 7)
  • Модератор Yui

    (@fierevere)

    永子

    if(current_user_can('publish_posts') )

    убрать
    заменить

    if ($user->has_cap('publish_posts'))

    а так?

    Та же трабла((
    Я не знаю, важно это или нет. Но юзер у меня принадлежит произвольному типу ролей. Может там особенности какие при работе с подобными ролями и правами

    /* Создаем новую роль пользователя reel */
    $new_role = add_role (
    'reel', // название роли
    __( 'Моя роль', 'r7'), // отображаемое название роли
    array( // массив возможностей
    'read' => true, // просмотр сайта
    'delete_posts' => true, // удаление собственных записей
    'edit_posts'=> true, // редактирование собственных записей
    'delete_published_posts' => true, // удаление собственных опубликованных записей
    'publish_posts'=> true, // публикация постов
    'upload_files'=> true, // загрузка файлов
    'edit_published_posts'=> true // редактирование собственных опубликованных записей
    ));
    if ( null !== $new_role ) { trigger_error("роль успешно создана"); /* смотрим результат - роль успешно создана */ }
    else { /* если null, то значит роль уже существует */ }

    Создание роли повешено на
    register_activation_hook(__FILE__, ‘r7i_set_options’);

    PS урезание прав повешено на
    add_action(‘publish_post’, ‘r7_control_package’, 0);
    (т.е. суть в чем. Я делаю лимитатор. Что каждый юзер можент опубликовать лишь по одному посту.)

    Модератор Sergey Biryukov

    (@sergeybiryukov)

    Live and Learn

    урезание прав повешено на
    add_action(‘publish_post’, ‘r7_control_package’, 0);

    Я бы сделал через фильтр map_meta_cap:

    function disallow_publish_posts( $caps, $cap, $current_user_id, $args ) {
    	if ( 'publish_posts' === $cap ) {
    		if ( count_user_posts( $current_user_id ) > 0 ) {
    			$caps[] = 'do_not_allow';
    		}
    	}
    
    	return $caps;
    }
    add_filter( 'map_meta_cap', 'disallow_publish_posts', 10, 4 );

    Спасибо за наводку. А можете чуточку пояснить код. В кодексе чет крайне мало нашел про map_meta_cap http://codex.wordpress.org/Function_Reference/map_meta_cap

    и не совсем уловил принцип его работы
    хотяб кратко подскажите что значат переменные
    $caps, $cap, $current_user_id, $args
    я так понимаю, что $caps — это массив?
    а еще что лежит у нас в $args ?

    я пока только вот что понял
    в $cap у нас то право, которе хотим урезать.
    $current_user_id — id того, кого урезаем.

    $caps у нас что? Все права которые есть у юзера или как? а в $args?

    И в какой момент map_meta_cap срабатывает? Т.е. к примеру я урезаю только юзеров из группы reel, админов и прочих не урезаю….

    вообще мой первичный код висел на add_action(‘publish_post’ и выглядел так.

    $cur_user_id = get_current_user_id(); // id текущего юзера
    $user = new WP_User( $cur_user_id ); // создаем экземпляр касса юзера
    $n_postov = get_the_author_meta('limit_postov', $cur_user_id); // получаем число оставшихся у юзера постов
    if (($n_postov == '')||$n_postov == '0') {
    $user->remove_cap( 'publish_posts' ); // и урезаем права
    if(current_user_can('publish_posts') ){
    echo "У юзера есть право publish_posts!";
    } else {/*Отнимаетм от счетчика единичку*/}
    }
    Модератор Sergey Biryukov

    (@sergeybiryukov)

    Live and Learn

    Если сильно не углубляться, то в WordPress есть два типа возможностей:

    • «Примитивные», которые действуют для всех объектов. Пример: edit_posts, edit_published_posts, edit_others_posts, edit_private_posts и др.
    • «Мета-возможности», которые действуют для конкретного объекта в зависимости от контекста. Пример: edit_post, publish_post.

    Проверкой контекста как раз занимается функция map_meta_cap(), а фильтр позволяет дополнить этот механизм своими правилами, например:

    • Запретить редактирование конкретной записи.
    • Запретить конкретному пользователю определённое действие.
    • Разрешить пользователю действие в зависимости от условий.

    Если углубляться — возможно, будут полезны материалы:

    $cap у нас то право, которе хотим урезать.
    $current_user_id — id того, кого урезаем.

    Верно.

    $caps у нас что? Все права которые есть у юзера или как?

    Это массив возможностей, которыми пользователь должен обладать, чтобы совершить текущее действие $cap.

    Например, для редактирования чужой опубликованной записи у пользователя должны быть возможности edit_others_posts и edit_published_posts.

    Если в массив добавить строку do_not_allow, то действие будет запрещено.

    а в $args?

    Аргументы, переданные в вызывающую функцию current_user_can().

    Например, если проверять права на редактирование конкретной записи — current_user_can( 'edit_post', $post_id ) — в $args будет ID записи.

    В нашем случае не используется, привёл просто для примера 🙂

    И в какой момент map_meta_cap срабатывает?

    В момент проверки current_user_can( 'publish_posts' ).

    Т.е. к примеру я урезаю только юзеров из группы reel, админов и прочих не урезаю….

    Можно добавить проверку роли:

    function disallow_publish_posts( $caps, $cap, $current_user_id, $args ) {
    	if ( 'publish_posts' === $cap ) {
    		$user = get_userdata( $current_user_id );
    		$role = ( $user ) ? current( $user->roles ) : '';
    
    		if ( 'reel' === $role && count_user_posts( $current_user_id ) > 0 ) {
    			$caps[] = 'do_not_allow';
    		}
    	}
    
    	return $caps;
    }
    add_filter( 'map_meta_cap', 'disallow_publish_posts', 10, 4 );

    Сергей, спасибо ОГРОМНОЕ! Работает!
    Может кому понадобиться, ниже код с комментариями (как я это понял своими словами)

    function disallow_publish_posts( $caps, $cap, $current_user_id, $args ) {
    /* Этот фильтр срабатывает всякий раз, когда проверяются права на совершение того или иного действия. Срабатывает всегда при проверке current_user_can. В нашем случае в момент проверки current_user_can( 'publish_posts' ).
    $cap - право, которое проверяем (в нашем случае его надо урезать)
    $caps - массив со списком прав, которые необходимы для совершения определенного действия. Если к этим правам добавить $caps[] = 'do_not_allow'; - мы запретим данное действие в данный момент времени
    */
    if ( 'publish_posts' === $cap ) { // проверяется возможность публиковать запись
    $user = get_userdata( $current_user_id ); // получаем данные юзера
    $role = ( $user ) ? current( $user->roles ) : ''; // вытаскиваем его роль
    $n_postov = get_the_author_meta('limit_postov', $current_user_id); // получаем число оставшихся у юзера постов
    if (($n_postov == '')||$n_postov == '0') { // если счетчик постов на нуле
    if ( 'reel' === $role) { // и при этом юзер в группе reel
    $caps[] = 'do_not_allow'; // блокируем возможность прямой публикации поста (вместо этого WP подставит конпку "Отправить на утвеждение")
    }} else {$n_postov = $n_postov - 1; update_usermeta( $current_user_id, 'limit_postov', $n_postov );}
    } return $caps;}
     add_filter( 'map_meta_cap', 'disallow_publish_posts', 10, 4 );

    PS в моем случае для юеров в профиле создавался отдельный блок с «лимитом постов» (limit_postov)
    Последний вопрос. Как посоветуете активировать вверху сообщение, что мол «ваш лимит постов исчерпан». Чтобы выводилось на каждой страничке выше заголовков.

    Оповещения сделал через хук add_action(‘admin_notices’)! Спасибо. Тема решена!

Просмотр 7 ответов — с 1 по 7 (всего 7)
  • Тема «Не работает remove_cap» закрыта для новых ответов.