Back-End

26 mai, 2014

Liberando a capability unfiltered_html em uma instalação multisite no WordPress

Publicidade

Nessa semana que culminará na 2ª edição do InterCon WP, me sinto instigado a escrever a respeito de um assunto talvez um pouco desconhecido pela maioria, mas que mais cedo ou mais tarde você poderá se deparar.

Dias atrás tive a necessidade de um usuário com a role Editor inserir um iframe diretamente no conteúdo de um post. Porém, ao realizar o salvamento, o código html do iframe era automaticamente excluído pelo WordPress. Na verdade, trata-se de um comportamento normal da plataforma, mas para usuários com as roles abaixo de Editor. Essa permissão, de salvar qualquer tipo de html em um post, é controlada pelo WordPress através da capability unfiltered_html, que por padrão é liberada nas roles de Administrador e Editor, exceto em uma instalação multisite, onde somente usuários com a liberação de Super Admin podem inserir esse tipo de conteúdo em um post.

A primeira abordagem, que funcionaria em uma instalação normal do WordPress para qualquer tipo de usuário, foi instalar um plugin de gerenciamento de Roles e Capabilities, como o WP Members, e fazer a liberação da capability unfiltered_html para a role Editor. Mas como estamos falando de uma instalação multisite do WordPress, isso não foi o suficiente para resolver a questão.

Pesquisando um pouco mais a fundo no core do WordPress, cheguei à função map_meta_cap() que faz o mapeamento de meta capabilities para capabilities primitivas da plataforma. Em uma condicional dentro dessa função encontraremos a seguinte lógica:

case 'unfiltered_html' :
		// Disallow unfiltered_html for all users, even admins and super admins.
		if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML )
			$caps[] = 'do_not_allow';
		elseif ( is_multisite() && ! is_super_admin( $user_id ) )
			$caps[] = 'do_not_allow';
		else
			$caps[] = $cap;
		break;

Notem que a primeira condicional nos apresenta uma constante, DISALLOW_UNFILTERED_HTML, que podemos utilizar no arquivo wp-config.php e desabilitar a inclusão de códigos html e javascript para todos os usuários. A segunda condicional é justamente o que nos trava em uma instalação multisite do WordPress, não adianta a role do usuário ter a capability unfiltered_html, se ele não for um Super Admin, não conseguirá incluir esse tipo de conteúdo.

Para “burlar” esse comportamento padrão e permitir que os usuários com a role Editor conseguissem salvar o post com o iframe no seu conteúdo utilizei o hook map_meta_cap, liberando através de uma função no tema a capability unfiltered_html.

add_filter( 'map_meta_cap', 'map_unfiltered_html', 99, 4 );
function map_unfiltered_html( $caps, $cap, $user_id, $args )
{
	$user = get_userdata( $user_id );

	if ( ( 'editor' == $user->roles[0] ) and ( 'unfiltered_html' == $cap ) ) :
		$caps = array( $cap );
	endif;

	return $caps;
}

Esse hook map_meta_cap é muito poderoso e útil para trabalhar as permissões de um usuário dentro do nosso projeto WordPress, mas cuidado com seu uso, certifiquem-se sempre se a liberação que estão dando está indo somente para os usuários desejados, caso contrário podemos criar grandes brechas de segurança em nossos plugins ou temas.

Para aprender mais sobre as Roles e Capabilites do WordPress visite o artigo do Codex que fala a respeito. E nunca se esqueça de usar o core da plataforma como aliado a seus estudos, muita coisa vamos passar a entender realmente como funciona só depois de uma boa olhada no código fonte.

Não percam o InterCon WP 2014, o maior evento técnico de WordPress da América Latina, no próximo sábado, dia 31/05. Nos vemos lá.