Este artigo é a terceira parte da série Como Criar Plugins para WordPress. O WordPress é uma das ferramentas para gestão de sites que tem vindo a crescer mais rapidamente nos últimos anos. Uma das razões provém da sua arquitetura altamente extensível através de plugins a par com a sua API simples de implementar. Recentemente um dos nossos leitores contatou-nos indicando que estava tendo dificuldades em encontrar tutoriais WordPress sobre criar plugins, e sugeriu-nos então que publicássemos uma série de artigos sobre como criar plugins para WordPress, ideia essa que decidimos aceitar!

PÁGINAS DE PLUGINS NA ADMINISTRAÇÃO

Alguns plugins mais complexos exigem que o usuário, após a instalação, escolha algumas opções para ativar funcionalidades. É o caso de alguns plugins de cache, tais como o W3 Total Cache. Essa necessidade prende-se com o facto do criador do plugin querer, numa única instalação fornecer o máximo de funcionalidades dentro da área de atuação do mesmo.

Já todos vimos plugins que criam subpáginas no menu da administração. A maior parte das abordagens estão corretas, porém, a meu ver, são vários os autores de plugins que pecam de duas maneiras:

  1. Criar uma página nova para colocar apenas uma ou duas opções.
  2. Fornecer opções a mais ao usuário.

A primeira parte prende-se com a economia de espaço. Se, por exemplo, um plugin for escrito para de alguma maneira alterar links internos do site e houver necessidade de apresentar uma ou duas opções, o ideal seria aproveitar a página de Links Permanentes na administração e colocar lá essas opções, em vez de se criar uma nova página.

Fornecer muitas opções pode baralhar o usuário. A política do WordPress quanto a isto é bastante clara – fornecer o mínimo de opções e optar pela configuração que abranja mais usuários. Esta ideia traz organização e simplicidade ao WordPress.

Na verdade você pode criar plugins de plugins, isto é, plugins que extendem as funcionalidades de outros plugins, e assim, abranger um nicho de usuários com necessiades específicas.

Um dos casos mais extravagantes neste campo é o plugin para envio e gestão de newsletters MeeNews. Quando este plugin apareceu ocorreu um boom de reviews em vários blogs da especialidade. Muitos afirmavam ser o melhor plugin para WordPress. Na verdade, ele funciona bastante bem, mas apenas quando configurado corretamente. Por ter demasiadas opções, torna o processo de configuração exageradamente complexo e, sendo assim, os usuários acabam por desistir da instalação. Os factos estão à vista: o ranking está bastante baixo e o forum tem muitos threads não respondidos.

Estando aqui o aviso feito, passemos então ao estudo de como criar páginas de opções e agregar opções a páginas nativas do WordPress.

Como criar uma página na administração do WordPress

Vamos criar uma página de administração dentro do menu “Opções” (Settings em inglês). Para isso servimo-nos da nosssa tão bem conhecida add_action():

<?php
add_action( 'admin_menu', 'ewp_pagina_opcoes' );

function ewp_pagina_opcoes() {
  // criamos a pagina de opções com esta função
  add_options_page( 'As Minhas Opções', 'Minhas Opções', 'manage_options', 'minhas-opcoes', 'ewp_pagina_opcoes_content' );

}

// Interior da página de Opções.
// Esta função imprime o conteúdo da página no ecrã.
// O HTML necessário encontra-se já escrito.
function ewp_pagina_opcoes_content() {
?>
<div class="wrap">
  <?php screen_icon(); ?>
  <h2>As Minhas Opções</h2>
  <form action="options.php" method="post">
    // Todo o conteúdo tem de vir aqui dentro
  </form>
</div>
<?php
}
?>

Como explicado no trecho de código, este é o mínimo necessário para se criar uma página. A função screen_icon() imprime o icon correspondente na página. Todos os inputs têm que ser guardados pela página options.php.

Registar opções de input para a página

Usando a API de Opções nativa do WordPress é a melhor maneira de podermos garantir que os dados serão armazenados e geridos pelo WordPress, e que este aplica todas as medidas de segurança necessárias aos inputs.

Para isso é necessário registar primeiro quais as novas opções que estamos a acrescentar e como é que as validamos:

<?php
// Vamos registar as nossas opções
add_action( 'admin_init', 'ewp_registar_opcoes' );

function ewp_registar_opcoes() {
  register_setting( 'ewp_as_minhas_opcoes', 'ewp_as_minhas_opcoes' );
  add_settings_section( 'ewp_opcoes_principais', 'Opções Gerais', 'ewp_opcoes_seccao', 'minhas-opcoes' );
  add_settings_field( 'ewp_opcao_1', 'Coloque o seu texto', 'ewp_opcao_1_input', 'minhas-opcoes', 'ewp_opcoes_principais' );

}

function ewp_opcoes_seccao() {
  echo '<p>Cabeçalho da página</p>';
}

function ewp_opcao_1_input() {
  // Vamos primeiro buscar a opção registada em cima...
  $opcao = get_option( 'ewp_as_minhas_opcoes' );
  $opcao_1 = $opcao['opcao_1'];

  // ... e agora vamos imprimir o campo de input com a opção
  echo '<input type="text" name="ewp_as_minhas_opcoes[opcao_1]" value="'.$opcao_1.'" />';

}
?>

Esta parte pode ser um tanto complicada, mas iremos por partes.

A primeira função register_setting() é responsável por dizer ao WP que vai ser criada uma nova opcção chamada ewp_as_minhas_opcoes sendo que esta deverá ser guardada na base de dados com o mesmo nome. Desta maneira o WordPress sempre que encontrar esta opção numa submissão de formulário na administração, saberá que deve atualizar a base de dados com o seu valor. De outro modo, se a opção não fosse registada, o WP apenas a ignorava.

A função add_settings_section() vai criar uma nova secção com um cabeçalho. Esta é a forma indicada de agrupar as várias opções. existem plugins que implementam uma estrutura de abas nestas páginas, sendo assim é necessário seguir esta forma de organização para que funcione com os usuários que pretendem a navegação por abas. Esta função aceita quatro argumentos:

  1. Um ID arbitrário para identificar a secção nos inputs.
  2. O cabeçalho que será exibido. Pode-se usar o sistema de tradução universal incluído no WordPress __( ‘String para traduzir’ ).
  3. A função a chamar, para que possa ser colocado algum texto depois do cabeçalho e antes das opções.
  4. A slug (link) da página onde se pretende que a secção apareça. Se colocar por exemplo options-general.php esta secção aparecerá na página de Opções Gerais.

A função add_settings_field() adiciona uma opção e imprime o HTML necessário. Aceita como argumentos:

  1. Um identificador do campo / opção.
  2. A label para esse campo.
  3. A função que irá imprimir o HTML.
  4. A slug da página onde quer que apareça.
  5. A secção onde quer agrupar as opções.
Esta função pode ser usada para criar vários campos de opções. Por exemplo, se você quiser criar cinco campos individuais, terá que chamar cinco vezes esta função, cada uma chamando a sua função específica no código. Também poderá criar as secções que queira.

A aqui uma screenshot do resultado final:

ADICIONAR CAMPOS NAS PÁGINAS DA ADMINISTRAÇÃO JÁ EXISTENTES

Claro que é possível, como já foi dito em cima, criar campos de opções e associá-los a páginas já existentes em vez de se criar uma nova página.

Para exemplificar isso, vamos criar um campo novo na página de Privacidade:

<?php
add_action( 'admin_init', 'ewp_opcoes_privacidade' );

function ewp_opcoes_privacidade() {
  // Vamos registar a opção com o WordPress
  register_setting( 'privacy', 'ewp_as_minhas_opcoes' );

  // Adicionar o campo na página de Privacidade
  add_settings_field( 'ewp_opcao_1', 'Um campo customizado', 'ewp_opcao_1_input', 'privacy', 'default' );

}
?>

E este é o resultado final:

ACESSO À BASE DE DADOS

O WordPress usa pouco SQL para acessar a base de dados. Em vez disso, toda a conecção é efetuado através da class WPDB, baseado no código EzSQL. Esta classe gere todas as tabelas da base de dados e seus conteúdos. É responsável por toda a conexão do WordPress.

É possível obviamente usarmos essa classe para criarmos a nossas próprias tabelas, ou simplesmente retirar ou guardar dados usando SQL. Embora os developers sugerem a utilização dos Custom Post Types e da tabela wp_posts para guardar dados, por vezes é necessário criar uma tabela específica pois a sua estrutura é muito diferente.

Por vezes, como é o caso do nosso exemplo, criar uma nova tabela pode ser mais benéfico. Se você pretender guardar os IPs dos seus usuários que visitam o site, é preferível colocá-lo noutra tabela, pois devido à grande quantidade de dados envolvida, usar a wp_posts poderia causar lentidão do site.

Criando uma nova tabela na base de dados

<?php

// Vamos criar uma tabela que irá guardar os IPs dos usuários que
// acessam o nosso website.
// ATENÇÃO: Este código é apenas didático. Se o usar para produção
// poderá vir a sofrer tempos de resposta maiores, pois irá guardar
// muitos dados na base de dados.

add_action( 'init', 'ewp_create_table' );

function ewp_create_table() {
  // Acesso ao objeto global de gestão de bases de dados
  global $wpdb;

  // Vamos checar se a nova tabela existe
  // A propriedade prefix é o prefixo de tabela escolhido na
  // instalação do WordPress
  $tablename = $wpdb->prefix . 'hits';

  // Se a tabela não existe vamos criá-la
  if ( $wpdb->get_var( "SHOW TABLES LIKE '$tablename'" ) != $tablename ) {

    $sql = "CREATE TABLE `$tablename` (
         `id` INT( 11 ) NOT NULL AUTO_INCREMENT,
         `hit_ip` VARCHAR( 100 ) NOT NULL,
         `hit_date` DATETIME
    );";

    // Para usarmos a função dbDelta() é necessário carregar este ficheiro
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );

    // Esta função cria a tabela na base de dados e executa as otimizações
    // necessárias.
    dbDelta( $sql );

  }

}
?>

Para completar o nosso código de registo dos IPs dos usuários, vamos criar criar o nosso procedimento para guardar os registos na tabela:

<?php

// Devido à quantidade de dados que esta função poderia gerar,
// vamos apenas atualizar a base de dados de 10 em 10 minutos.
// Desta forma, se um usuário permanecer no site por 30 minutos,
// será registado três vezes na tabela.

add_action( 'init', 'ewp_regist_ips' );

function ewp_regist_ips() {
  global $wpdb;

  // IP do usuário
  $ip = $_SERVER["REMOTE_ADDR"];

  // A Hora a que o usuário acessou
  $current_time = current_time( 'mysql' );

  // Vamos selecionar da base de dados os IPs registados à
  $id = $wpdb->get_var("SELECT id FROM ".$wpdb->prefix."hits WHERE hit_ip = '$ip' AND hit_date BETWEEN '.date("Y-m-d H:i:s", time() - 10 ).' AND '$current_time';");

  // Checamos se não existe nenhum registo procedemos
  if ( ! $id ) {
    // Registar os IPs na base de dados
    $novo_ip = array(
      'hit_ip' => $ip,
      'hit_date' => $current_time,
    );

    // Guardar os valores na tabela
    $wpdb->insert( $wpdb->prefix . "hits", $novo_ip );

  }

}
?>

E aqui temos um plugin que poderá ser colocado no functions.php do seu tema.

Poderá fazer o download deste plugin no rodapé deste artigo.

Neste trecho de código nós vimos dois novos métodos do objeto $wpdb. O método insert() insere novos dados na base de dados usando apenas um array. O método get_var(), usando SQL, conseguimos buscar dados às tabelas da base de dados.

Existem também outros métodos:

  • get_row( $sql ) : usando SQL, você poderá ir buscar qualquer linha na base de dados. O método retorna um array associativo.
  • get_results( $sql ) : caso pretenda buscar várias linhas no SQL, este método retorna-lhe um array de arrays, cada um deles associativo.
  • update( $nome_da_table, $data ) : este método é similar ao insert(), porém você deverá passar a chave primária (id) da linha que quer atualizar.
Para mais informações acerca desta classe, poderá ver aqui no site do Codex.

PLUGGABLE FUNCTIONS

As funções plugáveis, são funções carregadas pelo WordPress após todos os plugins estarem carregados, permitindo aos autores reescreverem essas funções da maneira que quiserem.

Todas as funções dentro do ficheiro wp-includes/pluggable.php podem ser rescritas. Basta o autor de plugin colocar no ficheiro principal uma função com o mesmo nome.

É muito natural os autores reescreverem a função wp_mail() – que se encontra nesse ficheiro – para poderem enviar emails do WordPress através de um servidor SMTP.

Não me vou alongar nesta matéria pois as possibilidades são inifinitas, ficando apenas a nota que você pode reescrever as funções que se encontram nesse ficheiro a seu gosto.

DOWNLOAD DO CÓDIGO

Este código serve apenas pra fins didáticos e não deve ser usado em sites de produção. Poderá fazer o download do código didático aqui.

Download do Código do Artigo

DOWNLOAD DO PLUGIN DE REGISTOS DOS IPS

Criámos um plugin especial para este artigo, baseado no código apresentado.

Este plugin regista os IPs dos seus usuários numa tabela customizada para depois poder acessar através de uma página da administração, no menu Ferramentas.

Plugin Registo de IP

NOTAS FINAIS

Ao criar o seu plugin tenha sempre em conta ser o mais responsável para com a instalação dos seus usuários. Se você tiver a necessidade de criar uma tabela na base de dados, por exemplo, faça-o apenas na ativação do plugin e não se esqueça de implementar uma função de remoção da tabela na desinstalação do plugin. O procedimento é o mesmo.

No próximo artigo iremos falar apenas e exclusivamente sobre segurança nos plugins e no WordPress em geral, hábitos e padrões que devem ser seguidos, matéria que tenho andado a adiar nos últimos artigos.

Espero que este artigo tenha sido útil, continuem a percorrer esta série. :)

Abraço,

Vitor