Customizando a query para buscar todos os dados do usuário no WordPress

O WordPress conta com ferramentas muito boas para administrar os usuários e permite que você estenda o formulário infinitamente. Entretanto, quando falamos em resgatar estes dados fora do WordPress, para exportar para uma base excel por exemplo, fica complicado pois como as informações não ficam em colunas nas tabelas, ou você cria uma query que vai te retornar linha a linha as meta keys duplicando todos os dados da tabela users ou utiliza um código externo redundante em PHP que vai sobrecarregar o seu servidor e obrigá-lo a rever o timeout da aplicação ou ainda pior, terá que gerar um plugin só para utilizar as funções do WordPress e te retornar estes dados e que também pode vir a dar problema de timeout.

Então qual a solução mais rápida? Extrair estes dados diretamente da sua base MySQL, utilizando o concatenamento de tabelas por meio da função JOIN do SQL.

SELECT
  u1.id,
  u1.user_email,
  u1.user_pass,
  u1.user_email,

  m1.meta_value AS firstname,
  m2.meta_value AS lastname,
  m3.meta_value AS birthday
  [...]
FROM 
  wp_users u1 
JOIN 
  wp_usermeta m1 ON (m1.user_id = u1.id AND m1.meta_key = 'first_name') 
JOIN 
  wp_usermeta m2 ON (m2.user_id = u1.id AND m2.meta_key = 'last_name') 
JOIN 
  wp_usermeta m3 ON (m3.user_id = u1.id AND m3.meta_key = 'birthday')
  [...]
WHERE
  [...]

Muito mais simples, não?

Custom SQL no WordPress

As funções do WordPress são muito úteis e na maioria das vezes o programador não necessita sequer pensar em banco de dados, conexão, select e outros termos que são de uso corrente em uma pesquisa em banco de dados com PHP. Entretanto, mesmo com toda essa facilidade de pesquisa, existem alguns casos em que não é possível escapar de customizar a query para obter os resultados com menor uso de memória e evitar também o timeout da aplicação.

Uma boa referência do que será tratado aqui pode ser visto de forma mais ampla em http://codex.wordpress.org/Class_Reference/wpdb.

Preparei aqui uma busca customizada no banco para pesquisar

$sql = "SELECT wusers.ID,
               wmeta.user_id, 
               wmeta.meta_key, 
               wmeta.meta_value
        FROM 
               $wpdb->users wusers
        INNER JOIN 
               $wpdb->usermeta wmeta
	ON 
                wusers.ID = wmeta.user_id
	WHERE 
                wmeta.meta_key = 'Twitter'
	ORDER BY 
                wmeta.meta_value ASC";

Então estamos pedindo para selecionar os campos ID da tabela users e user_id, meta_key e meta_value da tabela usermeta onde o campo meta_key é igual a Twitter e mandamos ordenar pelo valor. Observe que nesse caso eu estou citando um campo que foi personalizado, mas poderíamos pesquisar por first_name, last_name ou qualquer outro meta_key registrado. Em caso de dúvida consulte o post Melhorando o formulário de cadastro no WordPress.

Tendo a sintaxe SQL, vamos utilizar as funções do próprio WordPress para processar os resultados.

global $wpdb;

$users = $wpdb->get_results($sql);

foreach($users as $user){
  $uinfo = get_userdata($user->ID);  
  echo $uinfo->first_name . " : " . $uinfo->twitter<br />";
}

Com isso podemos gerenciar o cadastro de usuários, podemos fazer uma ficha com foto utilizando o Avatar por meio da função

get_avatar($user->ID);

ou mais completa:

get_avatar( $user->ID, 
            $tamanho = '96', 
            $img_padrao = 'http://www.seusite.com.br/avatar.jpg' )

Também é possível inserir diretamente o link para a imagem

$grav_url = "http://www.gravatar.com/avatar/" . 
             md5(strtolower($user->user_email)) . 
             "?d=" . urlencode($avatar_padrao) . 
             "&s=" . $tamanho;

echo "<img src='$grav_url'/>";

Agora é usar a criatividade e a necessidade para otimizar os seus resultados.

Melhorando o formulário de cadastro do WordPress

Existem uma série de plugins que gerenciam para você o cadastro de usuários no WordPress adicionando ou retirando campos, entretanto diversas vezes os achei muito limitados e até difíceis de gerenciar pelo usuário comum.

O problema que eu vejo em se utilizar plugins que são feitos por terceiros é que você sempre fica à mercê das atualizações promovidas pelo desenvolvedor ou a própria descontinuação do projeto. Então, exceto pelos plugins que são de desenvolvedores ou empresas conhecidas, eu prefiro sempre que possível fazer a minha implementação.

Neste exemplo não construirei um plugin, mas indico como fazer o uso das funções do WordPress para gerenciar o cadastro de usuários.

Primeiramente devemos relacionar o que queremos em nosso formulário.

  • Nome
  • Email
  • Twitter
  • Telefone
  • Endereço
  • Bairro
  • Cidade
  • Estado
  • CEP

A seguir, baseado no formulário de cadastro que o WP disponibiliza vamos personalizar o nosso. Iniciaremos excluindo alguns campos que não são necessários.

add_filter('user_contactmethods','add_contactmethod',10,1);

function add_contactmethod( $contactmethods ) {
  $contactmethods['user_twitter'] = 'Twitter';
  $contactmethods['user_telephone'] = 'Telefone';

  unset($contactmethods['aim']);
  unset($contactmethods['jabber']);
  unset($contactmethods['yim']);

  return $contactmethods;
}

A variável $contactmethods contempla todas os campos referentes às informações de contato. Poderíamos já incluir nesta função todos os campos que queremos como o de endereço e bairro, mas ficaria confuso misturar esse tipo de informação, então para esta situação, iremos criar uma seção exclusiva para estas informações extras. Em resumo, para adicionar campos utilize $contactmethods[‘nome_do_campo’] = ‘Label do Campo’ e para excluir um existente utilize a função do php unset($contactmethods[‘nome_do_campo’]).

Então já temos assim os campos Nome e email (padrão do WordPress) e agora acabamos de adicionar Twitter e Telefone. Vamos agora criar o formulário interno com os novos campos tanto para inserção quanto para atualização de cadastro.

add_action( 'show_user_profile', 'extra_info_profile_fields' );
add_action( 'edit_user_profile', 'extra_info_profile_fields' ); 

function extra_info_profile_fields($user) { ?>
<h3>Informações extras</h3>
  <table>
    <tr>
      <th><label for="user_address">Endereço</label></th>
      <td>
        <input type="text" name="user_address" id="user_address" value="<?php echo esc_attr( get_the_author_meta( 'user_address', $user->ID ) ); ?>" /><br />
        <span>Preencha o seu endereço.</span>
      </td>
    </tr>
    <tr>   
      <th><label for="user_district">Bairro</label></th>
      <td>
        <input type="text" name="user_district" id="user_district" value="<?php echo esc_attr( get_the_author_meta( 'user_district', $user->ID ) ); ?>" /><br />
        <span>Preencha com o seu bairro.</span>
      </td>
    </tr>
    <tr>
      <th><label for="user_city">Cidade</label></th>
      <td>
        <input type="text" name="user_city" id="user_city" value="<?php echo esc_attr( get_the_author_meta( 'user_city', $user->ID ) ); ?>" /><br />
        <span>Preencha com a sua cidade. </span>
      </td>
    </tr>
    <tr>
      <th><label for="user_state">Estado</label></th>
      <td>
       	<input type="text" name="user_state" id="user_state" value="<?php echo esc_attr( get_the_author_meta( 'user_state', $user->ID ) ); ?>" /><br />
        <span>Preencha com o seu estado. </span>
      </td>
    </tr>
    <tr>
      <th><label for="user_zipcode">CEP</label></th>
      <td>
        <input type="text" name="user_zipcode" id="user_zipcode" value="<?php echo esc_attr( get_the_author_meta( 'user_zipcode', $user->ID ) ); ?>" /><br />
        <span>Digite o seu CEP. </span>
      </td>
    </tr>
 </table>

<?php }
add_action( 'personal_options_update', 'save_extra_info_profile_fields' );
add_action( 'edit_user_profile_update', 'save_extra_info_profile_fields' ); 

function save_extra_info_profile_fields( $user_id ) {
  if ( !current_user_can( 'edit_user', $user_id ) ) {
    return false;
  } 
  update_usermeta( $user_id, 'user_address', $_POST['user_address'] );
  update_usermeta( $user_id, 'user_district', $_POST['user_district'] );
  update_usermeta( $user_id, 'user_city', $_POST['user_city'] );
  update_usermeta( $user_id, 'user_state', $_POST['user_state'] );
  update_usermeta( $user_id, 'user_zipcode', $_POST['user_zipcode'] );
}

A função criada abaixo faz uso da função do WordPress wp_insert_user, que serve exclusivamente para criar o cadastro do usuário, mas ela só responde pelos campos padrão e pelos campos criados por meio do hook user_contactmethods. E os outros campos? Caso a função seja concluída, ela nos retorna o ID do usuário cadastrado, pegamos esse ID e mandamos atualizar o cadastro. Para mais informações sobre esta função acesse http://codex.wordpress.org/Function_Reference/wp_insert_user e para a função de atualizar o cadastro http://codex.wordpress.org/Function_Reference/wp_update_user.

function criar_usuario($firstname, $lastname, $nickname, $user_nicename, $user_email, $display_name, $user_site, $user_blog, $user_twitter, $user_telephone, $user_login, $user_pass, $user_role="subscriber"){
    $user_data = array();
    $user_data["first_name"] = $firstname;
    $user_data["last_name"] = $lastname;
    $user_data["nickname"] = $nickname;
    $user_data["user_nicename"] = $user_nicename;
    $user_data["user_email"] = $user_email;
    $user_data["display_name"] = $display_name;
    $user_data["user_url"] = $user_site;
    $user_data["user_blog"] = $user_blog;
    $user_data["user_twitter"] = $user_twitter;
    $user_data["user_telephone"] = $user_telephone;
    $user_data["user_login"] = $user_login;
    $user_data["user_pass"] = $user_pass;
    $user_data["role"] = $user_role;

    return  wp_insert_user( $user_data );
    update_user();
}
function update_user($user_id, $address, $district, $city, $state, $zipcode){
  if(!is_wp_error($user_id)){
    update_user_meta( $user_id, 'user_address', $address);
    update_user_meta( $user_id, 'user_complement', $complement);
    update_user_meta( $user_id, 'user_district', $district);
    update_user_meta( $user_id, 'user_city', $city);
    update_user_meta( $user_id, 'user_state', $state);
    update_user_meta( $user_id, 'user_zipcode', $zipcode);
  }
}

Para efetivar o seu cadastro, basta criar o seu formulário e na página de processamento chamar as funções acima criadas com as suas respectivas variáveis preenchidas.

 

Plugins Sugeridos

Register Plus
http://wordpress.org/extend/plugins/register-plus/

Simplr Registration Form
http://wordpress.org/extend/plugins/simplr-registration-form/

Register Plus Redux
http://wordpress.org/extend/plugins/register-plus-redux/

Enviar email no formato HTML via WordPress

Para o envio de email o WordPress faz uso da função wp_mail() que disponibilizam os seguintes argumentos para serem trabalhados:

wp_mail( $destinatario, $assunto, $mensagem, $headers, $anexos );

Os dois últimos argumentos são opcionais.

Por padrão, esta função somente envia emails no formato texto, sem formatação, ou seja, qualquer tag html que exista no seu email será mostrada ao usuário por extenso.

Para resolver este problema, existem duas formas de trabalhar essa função para que ela exiba corretamente as suas tags html.

A primeira e mais simples é adicionando o content-type diretamente na variável $header:

$headers = array("From: Wildiney <criacao@wildiney.com>",
	         "Content-Type: text/html"
	         );

Se forem poucos os lugares onde você fará uso desta função, o exemplo acima resolve perfeitamente. Agora se o uso for constante, você pode configurar diretamente no arquivo functions.php.

add_filter('wp_mail_content_type','set_contenttype');

function set_contenttype($content_type){
  return 'text/html';
}

Existe também uma versão mais resumida da função acima que eu encontrei em alguns fóruns.

add_filter('wp_mail_content_type', create_function('', 'return "text/html"; '));

Nesse caso fica a gosto, não notei nenhuma diferença no desempenho, apesar de acreditar que usar a função do php create_function possa gerar mais processamento do que explicitar diretamente o que quer.

Integrar a biblioteca Zend com WordPress

Procurando uma forma de integrar a biblioteca do Zend Framework para implementar algumas funcões do WordPress, pesquisei em alguns sites algumas sugestões de como proceder. O resultado postado abaixo sugere uma mescla dos diversos resultados encontrados adaptados à minha atual necessidade. Os sites usados na pesquisa encontram-se relacionados abaixo.

Faça o download do Zend Framework Minimal Package no site da Zend (http://www.zend.com/community/downloads)

Descompacte e transfira a pasta library para a raiz do seu template.

No arquivo functions.php insira o código abaixo que fará o include da biblioteca Zend no WP.

set_include_path(
  get_include_path() .
  PATH_SEPARATOR .
  dirname(__FILE__) .
  DIRECTORY_SEPARATOR .
  'library'
);
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();

A partir de agora, qualquer chamada às classes do Zend Framework pelo seu template retornará resultado. Para testar insira o código abaixo em algum arquivo do wordpress, pode ser o single.php se for visualizar um post ou  page.php se for visualizar uma página padrão.

$data = new Zend_Date();
echo $data; // Exibe a data corrente de acordo com o padrão do servidor
$data->toString('YYYY-MM-dd'); // Formata a data no padrão descrito na string

Mas e como fazer para usar as classes que traballham com banco de dados, como o Zend_Db_Table?

No arquivo functions.php, faça a chamada do método Zend_Loader e configure o acesso ao banco de dados.

Zend_Loader::registerAutoload();
$db = Zend_Db::factory('Pdo_Mysql', array(
  'host'          => 'localhost',
  'username'      => 'usuario',
  'password'      => 'senha',
  'dbname'        => 'nomedobanco'
  ));

Zend_Db_Table::setDefaultAdapter($db);

Para cada tabela no banco de dados você deve criar uma classe semelhante a descrita abaixo. Para quem já conhece POO será fácil compreender a estrutura e os elementos.

class Users extends Zend_Db_Table_Abstract {
  protected $_name = 'wp_users';
  }

Para fazer as pesquisas faça a chamada das funções no seu template.

$users = new Users();
$users = $users->fetchAll()->toArray();

echo "<pre>";
  print_r($users[0]);
echo "</pre>";

Não tenho certeza se esse é o método mais seguro ou o mais prático, talvez dê para colocar a configuração do banco no wp-config.php, enfim, ainda serão necessários alguns testes para moldar qual a melhor forma.

Existe um método mais intrusivo descrito em http://www.krotscheck.net/2009/05/16/bootstrapping-a-startup-zend-and-wordpress-auth-integration.html mas que demanda muito mais conhecimento.

Qualquer sugestão a respeito, envie seu comentário.

Referências

http://stackoverflow.com/questions/377628/can-i-integrate-a-zend-framework-powered-web-application-into-a-wordpress-site

http://pt.w3support.net/index.php?db=so&id=377628

http://www.projeteweb.com.br/blog/como-integrar-o-zend-framework-em-um-tema-wordpress

 

Atualizar WordPress via SSH

Em algumas hospedagens eu encontrei um problema persistente que faz com que mesmo a pasta tendo chmod 777, o servidor bloqueia a atualização automática do wordpress, ou até mesmo por falta de memória disponível nas hospedagens compartilhadas quando aparece o erro de Timeout.

Procurando uma forma de fazer as atualizações de forma rápida e segura, me deparei com a possibilidade de fazer via SSH. Existem alguns posts falando a respeito, entretanto não encontrei nenhum que falasse como fazer o processo para WordPress versão pt-br.

O processo é bem simples. Acesse o seu servidor via SSH, e insira os comandos abaixo:

wget http://br.wordpress.org/wordpress-3.1.1-pt_BR.tar.gz

Acessando o http://br.wordpress.org você pode pegar o link da versão tar.gz mais atual caso esta não seja.

Descompacte o arquivo.

tar xfz wordpress-3.1.1-pt_BR.tar.gz

Delete as pastas wp-include e wp-admin da sua instalação atual ou simplesmente renomeie caso queira ter como backup.

rm -rf ./wp-includes/
rm -rf ./wp-admin/

Acesse a pasta que você acabou de descompactar

cd wordpress

E copie sobrepondo os arquivos com o seguinte comando:

cp -rpf -f * ../

Volte para a sua instalação WordPress

cd ..

Delete os arquivos que você não usará mais.

rm -rf wordpress
rm -f wordpress-3.1.1-pt_BR.tar.gz

Acesse o admin do seu WordPress e atualize a sua rede.

Acessando servidor via SSH

O FTP é uma ferramenta muito útil para o tráfego de arquivos, entretanto dependendo da quantidade que se tenha para transferir, o processo fica muito lento devido a verificação de cada arquivo enviado.

Para estes casos, é possível compactar o arquivo, enviar via SSH e extrair diretamente no servidor. Um bom exemplo disso são os arquivos do Magento. A pasta compactada tem cerca de 15MB e para enviar estes arquivos via FTP com uma ótima conexão, não leva menos de duas horas. Via SSH em poucos minutos o temos o arquivo disponível.

Para acessar o servidor via SSH, utilize um programa como o Putty do Windows ou acesse via Terminal do MAC ou do Linux.

Insira o seguinte comando:

ssh usuario_ftp@seu_dominio.com.br

Será solicitado a sua senha. Insira e aparecerá o console para que você possa a partir dos comandos do Linux copiar, excluir, mover, descompactar, fazer downloads diretamente em sua hospedagem.

Os principais comandos para você usar via SSH são

ls - listar arquivos (ex.: ls -la)
cp - copiar arquivos (ex.: cp file.txt pasta/filecopied.txt)
mv - mover arquivos (ex.: mv file.txt pasta/filemoved.txt)
rm - deletar arquivos ou diretrórios (ex.: rm -Rf dir)
wget - fazer o download de arquivos
tar - descompactar arquivos compactados com a extensão .tar.gz (ex.: tar -xfz arquivo.tar.gz)

O que fazer após instalar o wordpress?

Plugins

DB Backup – Efetua automaticamente o backup das tabelas da sua instalação wordpress. Recomendado utilizar a opção de enviar por backup por email e nunca usar a opção para salvar em pasta no seu servidor.

Maintenance Mode – Exibe uma mensagem de manutenção  para todos os usuários, exceto para os administradores.

Search & Replace – Efetua pesquisas em seu banco de dados e substitui de acordo com a opção configurada.

Clean WP Dashboard – Desabilita opções do dashboard para facilitar a vida do seu cliente.

WP No Category – Reescreve a url para tirar o /category/ do link. Atenção pois com a desativação de categoria pode ocorrer conflitos entre páginas e categorias.

wp-config.php

Para que toda vez que você precise atualizar o WordPress ou seus plugins, não seja solicitada se senha de ftp. Abra o wp-config.php e acrescente as seguintes linhas:

define('FTP_BASE', '/suainstalacaowordpress');
define('FTP_CONTENT_DIR', '/suainstalacaowordpress/wp-content/');
define('FTP_PLUGIN_DIR', '/suainstalacaowordpress/wp-content/plugins/');
define('FTP_USER', 'login');
define('FTP_PASS', 'senha');
define('FTP_HOST', 'ftp.seusite.com.br');
define('FTP_SSL', false);

Para sobrescrever a url do seu site sobre o informado no banco de dados utilize:

define('WP_SITE_URL', 'http://www.seusite.com.br');
define('WP_HOME', 'http://www.seusite.com.br');

Neste ponto é interessante utilizar o plugin search & replace para procurar pela url antiga nos seus posts e definições da base de dados. Lembrando que sempre que for utilizar este plugin faça o backup da base de dados.

define('FTP_CONTENT_DIR', '/suainstalacaowordpress/wp-content/');

Habilitando a opção Multi Site do WordPress 3.0

Ter em um mesmo domínio diversos sites, poder gerenciar todos de forma simplificada e ainda possibilitar o acesso individual é um trabalho que até pouco tempo atrás demandava horas de planejamento e muito mais de programação.

A partir do WordPress 3.0, a antiga versão MU que auxiliava no processo de instalação múltipla foi incorporada à versão bastando somente ser habilitada ao fim da instalação normal.

Proceda normalmente com a instalação simples do WordPress 3.0.

Na raiz da sua instalação, abra o arquivo wp-config.php e acima da linha que diz:

/* Isto é tudo, pode parar de editar! */

Digite:

define('WP_ALLOW_MULTISITE', true);

Para dar continuidade no processo é importante que todos os plugins estejam desativados. Feito isso acesse o menu Ferramentas e verá que surgiu um novo link chamado Rede. Acesse este link e com atenção preencha as informações pedidas.

  • Título da Rede
  • Endereço de email do administrador
  • Opção subdomínio ou pasta relativa (se for uma instalação localhost este item não aparecerá, a opção padrão é pasta relativa).

Para este processo eu não vou utilizar subdomínio que necessita de outros requisitos e caso tenha interesse pode ver mais a respeito em http://codex.wordpress.org/Create_A_Network.

Clique em instalar.

Neste ponto é importante que faça o backup do seu arquivo wp-config.php e .htaccess, se for a primeira instalação ou ainda não tiver customizado a sua instalação, provavelmente não terá ainda o arquivo .htaccess.

Crie abaixo da pasta wp-content uma nova pasta e dê o nome de blogs.dir. É importante que essa pasta tenha permissão de leitura e escrita (chmod 777).

Conforme descrito no item 2 da página de instalação, adicione ao arquivo wp-config.php, logo acima da linha:

/* Isto é tudo, pode parar de editar! */

o conteúdo do box branco que deve ser parecido com este:

define( 'MULTISITE', true );
define( 'SUBDOMAIN_INSTALL', false );
$base = '/';
define( 'DOMAIN_CURRENT_SITE', '*******' );
define( 'PATH_CURRENT_SITE', '/' );
define( 'SITE_ID_CURRENT_SITE', 1 );
define( 'BLOG_ID_CURRENT_SITE', 1 );

Adicione também as chaves de autenticação exibidas no segundo box:

define( 'AUTH_SALT', '******************************' );
define( 'SECURE_AUTH_SALT', '******************************' );
define( 'LOGGED_IN_SALT', '*******************************' );
define( 'NONCE_SALT', '*****************************' );

Crie ou edite o arquivo .haccess que está na raiz da sua instalação e adicione o conteudo do terceiro box:

RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]

# uploaded files
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L]
RewriteRule . index.php [L]

Agora, se você acessar seu painel administrativo verá que foi criado um grupo de links com o título Super-Admin. Neste grupo de links que você vai gerenciar os sites que serão criados.