Neste post vamos falar um pouco sobre como funciona o esquema de permissões de usuário no WordPress: o que cada usuário pode ou não fazer. Boa parte do texto foi adaptado da documentação oficial e do manual de plugins.

Como qualquer gerenciador de conteúdo, existe uma série de tarefas possíveis de executar dentro do WP. Por exemplo:

  • Publicar posts
  • Editar usuários
  • Moderar comentários
  • Instalar plugins
  • etc.

Cada uma destas tarefas está relacionada a uma capacidade, ou capability: publish_posts, edit_users, moderate_comments e activate_plugins são as capacidades dos exemplos acima.

Para relacionar as capacidades e os usuários existem as funções, ou roles. Por padrão, cada usuário no WordPress recebe uma função e esta função agrupa uma série de capacidades.

Funções padrão do WordPress

Vou deixar aqui a lista com as funções que já vem no WordPress e suas descrições.

  • Superadministrador: Existe somente em instalações multisite. Usuários com esta função podem fazer tudo, inclusive acessar recursos de gerenciamento do multisite, como atualizar o WordPress, criar novos sites e ativar plugins em toda a rede.
  • Administrador: Usuários com esta função pode acessar todos os recursos de administração de um site. Em instalações comuns, ou seja, não-multisite é o nível mais alto.
  • Editor: Esta função engloba todas as capacidades relacionadas à administração de conteúdo. Editores podem criar, editar e excluir páginas e posts, incluindo os de outros usuários. Eles também podem gerenciar categorias e moderar comentários.
  • Autor: Um usuário com esta função pode criar, publicar, editar e excluir seu próprio conteúdo. Eles também podem enviar arquivos para o WordPress.
  • Colaborador: Usuários com esta função podem gerenciar seu próprio conteúdo, mas não podem publicá-lo nem enviar arquivos para o WP.
  • Assinante: Função mais básica. Usuários assinantes podem apenas gerenciar seu próprio perfil e acessar o conteúdo.

A documentação oficial fornece a lista com todas as capacidades de cada função.

É hora do código!

Feita essa explicação básica de como as coisas funcionam, chegou a hora de ver como isso tudo funciona no código.

Eu sei que você veio aqui atrás de código!

Apenas para evitar confusões, a partir deste ponto:

  • Função (com F maiúsculo) é a role do WordPress e
  • função (com f minúsculo) são funções de programação mesmo.

Como verificar capacidades no WordPress

Toda vez que você precisar saber se um usuário pode ou não executar uma tarefa você deve verificar se ele possui a capacidade e não a Função necessária.

user_can( $usuario, $capacidade )

Dado um usuário (seu ID ou um objeto WP_User), esta função retorna se ele tem ou não a capacidade informada. Esta função também aceita parâmetros adicionais, como o ID de alguma entidade, para verificações mais complexas. Você pode usar o filtro user_has_cap para estes cenários.

Alguns exemplos de uso tirados da documentação da função:

user_can( $user->ID, 'edit_posts' );
user_can( $user->ID, 'edit_post', $post->ID );
user_can( $user->ID, 'edit_post_meta', $post->ID, $meta_key );

current_user_can( $capacidade )

Esta função é idêntica à anterior, mas usa o usuário atual para a verificação. Como na maioria das vezes escrevemos código para testar a permissão do usuário logado no momento, é mais comum vermos essa função do que a outra. Parâmetros adicionais também são aceitos para dar mais contexto em alguns cenários.

Alguns exemplos de uso tirados da documentação da função:

current_user_can( 'edit_posts' );
current_user_can( 'edit_post', $post->ID );
current_user_can( 'edit_post_meta', $post->ID, $meta_key );

current_user_can_for_blog( $blog_id, $capacidade )

Útil somente para multisites. Exatamente igual à função anterior, mas recebe o ID do site como primeiro parâmetro. Esta função troca o contexto para o site passado como parâmetro (switch_to_blog( $blog_id )), faz a verificação e retorna o contexto para o site anterior se necessário (restore_current_blog()).

Mais informações na documentação da função.

Como criar, editar e excluir Funções e suas capacidades no WP

Se você quer uma forma rápida e instalar plugins não é um problema para o seu projeto, talvez o User Role Editor resolva seu problema. Infelizmente, muitas vezes temos que desenvolver uma solução que não dependa de nenhum outro código, então temos que criar as nossas próprias Funções e capacidades.

Nunca é demais lembrar: Funções e capacidades são território de plugin no WordPress. Isso não deve estar no seu tema.

Como criar uma Função

Para criar uma Função no WordPress você deve usar a função add_role(). Esta função recebe o slug da Função, seu nome e suas capacidades.

Toda essa parte de Funções do WordPress é gravada no banco de dados. Você vai ver muitos códigos por aí chamando a função add_role() na action init. Muitos. Essa abordagem funciona, mas para um desempenho ligeiramente melhor, muitos plugins o colocam no processo de instalação. Na maioria dos exemplos do post eu usei esta abordagem.

Se decidir fazer o seu código desse jeito e precisar mudá-lo depois, lembre-se sempre de desativar e ativar o plugin para que o WordPress perceba a mudança.

Para variar, este código foi adaptado da documentação da função:

function meu_plugin_cria_funcoes_na_ativacao() {
    add_role(
        'guest_author',
        __( 'Guest Author', 'testdomain' ),
        array(
            'read'         => true,  // true concede a permissão
            'edit_posts'   => true,
            'delete_posts' => false, // Use false para negar explicitamente
        )
    );
}
register_activation_hook( __FILE__, 'meu_plugin_cria_funcoes_na_ativacao' );

Se a sua nova Função será baseada em uma já existente, você pode pegar as capacidades da Função original e passá-las como parâmetro:

function meu_plugin_cria_funcoes_na_ativacao() {
    $adm = get_role( 'administrator' );

    add_role(
        'new_admin',
        __( 'New Admin', 'testdomain' ),
        $adm->capabilities
    );
}
register_activation_hook( __FILE__, 'meu_plugin_cria_funcoes_na_ativacao' );

A versão original deste código está no StackExchange do WordPress.

Como editar uma Função

Trocar o nome de uma Função do WordPress

Se precisar editar o nome de uma função, você pode usar o código a seguir. Ele pega a variável global $wp_roles e a altera da forma necessária. A versão original deste snippet é do pessoal da WPMU DEV.

function mudar_nome_colaborador() {
	global $wp_roles;
	if ( ! isset( $wp_roles ) ) {
		$wp_roles = new WP_Roles();
	}
	$wp_roles->roles['contributor']['name'] = 'Novo nome';
	$wp_roles->role_names['contributor']    = 'Novo nome';
}
add_action( 'init', 'mudar_nome_colaborador' );

Alterar as capacidades de uma Função

A classe WP_Role tem dois métodos para isso: add_cap() e remove_cap().

Mais um código retirado da documentação oficial:

function adiciona_cap_autor() {
    // Obtém o objeto WP_Role da Função author
    $role = get_role( 'author' );
 
    // Adiciona a capacidade de editor posts de outros usuários.
    $role->add_cap( 'edit_others_posts' ); 
}
add_action( 'admin_init', 'adiciona_cap_autor' );

Como excluir uma Função

Funções nativas do WordPress

Algumas recomendações da documentação oficial:

  • Aconselha-se não excluir as Funções de Administrador e Superadministrador;
  • Leve em conta que novas atualizações do WordPress podem adicionar as Funções novamente. Em casos assim é melhor colocar a sua função em um hook, ao invés de só executar na instalação do plugin;
  • Execute update_option( 'default_role', SUA_NOVA_FUNÇÃO ) caso esteja excluindo a Função padrão para novos usuários.

Funções criadas por um plugin seu

Se o seu plugin cria uma Função, use o hook de desativação para removê-la. Esse processo também é conhecido como limpe a sua bagunça.

Este artigo do pessoal do Kinsta tem vários detalhes interessantes sobre Funções e capacidades. Adaptei um trecho do código deles:

function meu_plugin_exclui_funcoes_na_desativacao() {
    remove_role( 'guest_author' );
}
register_deactivation_hook( __FILE__, 'meu_plugin_exclui_funcoes_na_desativacao' );

Capacidades para tipos de post personalizados ou CPT

Por padrão, as capacidades de gerenciamento de tipos de posts personalizados seguem as dos posts nativos. Se você precisa de capacidades diferentes para um CPT, no momento em que chamar a função register_post_type use o argumento capability_type ou o argumento capabilities para defini-las.

Usar capability_type é mais simples:

function book_setup_post_type() {
    $args = array(
        'public'          => true,
        'label'           => __( 'Story', 'textdomain' ),
        'menu_icon'       => 'dashicons-book',
        'capability_type' => array( 'story', 'stories' ), // Passando a string 'story', o WP usaria 'storys' como plural
    );
    register_post_type( 'story', $args );
}
add_action( 'init', 'book_setup_post_type' );

Usar capabilities dá mais liberdade:

function book_setup_post_type() {
    $args = array(
        'public'       => true,
        'label'        => __( 'Story', 'textdomain' ),
        'menu_icon'    => 'dashicons-book',
        'capabilities' => array(
            'read_post'              => 'read_story',
            'read_private_posts'     => 'read_private_stories',
            'edit_post'              => 'edit_story',
            'edit_posts'             => 'edit_stories',
            'edit_others_posts'      => 'edit_others_stories',
            'edit_published_posts'   => 'edit_published_stories',
            'edit_private_posts'     => 'edit_private_stories',
            'delete_post'            => 'delete_story',
            'delete_posts'           => 'delete_stories',
            'delete_others_posts'    => 'delete_others_stories',
            'delete_published_posts' => 'delete_published_stories',
            'delete_private_posts'   => 'delete_private_stories',
            'publish_posts'          => 'publish_stories',
            'moderate_comments'      => 'moderate_story_comments',
        ),
    );
    register_post_type( 'story', $args );
}
add_action( 'init', 'book_setup_post_type' );

Não se esqueça de dar as capacidades para as Funções necessárias!


Se você achou esse post útil, não esqueça de compartilhar com os seus amigos. Para receber notícias sobre os próximos posts, não esqueça de assinar o canal do YouTube e assinar a newsletter!