Modelo de Banco do BuddyPress 1.0

Estou disponibilizando agora o modelo de banco do bp 1.0, assim como o modelo do WP e o modelo do WPMU, esse não é uma representação fiel do banco e sim uma visualização simplificada para consulta. Devido a quantidade de tabelas existentes no BuddyPress, mantive apenas a tabela ‘users’ do WPMU, pois é a nela que se concentram a maioria dos relacionamentos do BP. Além disso também fiquei por fazer alguns relacionamentos que estavam confusos e ambiguos.

No arquivo estão o xml para edição no DBDesigner e uma imagem no formato png, conforme a apresentada abaixo.

bp-10

Opções de Widgets

Após criar um widget o próximo passo é adicionar algumas opções a ele, tornando-o mais flexível para o usuário final. Utilizando como exemplo o plugin de posts mais quentes, digamos que você tenha definido a quantidade de cinco posts para serem apresentados mas um usuário queira mostrar apenas três. Para essas situações utilizamos a seguinte função:

register_widget_control('Nome do Widget', 'sua_funcao_de_configuracao', 'largura', 'altura')
Formulário de configuração do Widget

Formulário de configuração do Widget

Essa função permite configurar as opções de seu widget onde ‘Nome do Widget’ é o nome do widget que deseja configurar (o mesmo que informou em ‘register_sidebar_widget’), ‘sua_funcao_de_configuracao’ é a função que deve ser chamada para configurar o plugin e ‘largura’ e ‘altura’ são opcionais e se referem ao tamanho do formulário de configuração.

A sua função de configuração deve possuir um formulário com os campos de configuração e uma rotina para salvar esses dados no banco. O seu formulário não deve conter as tags ‘form’ nem ‘submit’, pois eles são acrescentados automáticamente pelo WordPress de forma a englobar todos os widgets.

Vamos ver uma forma fácil de implementar essa configuração:

function configurar_posts_mais_quentes()
{
  // Inicializa as variáveis necessárias
  $options = array();

  // Salvando as opções
  if($_POST['salvar_posts_mais_quentes'])
  {
    $opcoes['quantidade'] = (int) $_POST['quantidade_de_posts_mais_quentes'];

    // Valor padrão, caso nada tenha sido informado
    if(empty($opcoes['quantidade'])) $opcoes['quantidade'] = 5;

    update_option('posts_mais_quentes', $opcoes);
  }

  // Carregar as opções desse widget
  $opcoes = get_option('posts_mais_quentes');

  // Formulário
  ?>
    <input type="hidden" name="salvar_posts_mais_quentes" value="1" />

    <p>
      <label for="quantidade_de_posts_mais_quentes">Quantidade:</label>
      <input type="text" name="quantidade_de_posts_mais_quentes" maxlength="2" value="<?php print $opcoes['quantidade']; ?>" class="widefat" />
    </p>
  <?php
}

Explicando… começando na linha 18 ($opcoes = get_option(‘posts_mais_quentes’)) carrega as opções desse widget do banco. Notem que usei a tabela ‘options’ do banco do WordPress para salvar as opções do plugins, como foi explicado no post plugins e banco de dados.

Agora vamos para o início do formulário na linha 22, onde adiciono um campo oculto (<input type=”hidden” name=”salvar_posts_mais_quentes” value=”1″ />) apenas para ter controle quando o formulário for enviado. Também adicionei um campo de texto na linha 26 (<input type=”text” name=”quantidade_de_posts_mais_quentes” maxlength=”2″ value=”<?php print $opcoes['quantidade']; ?>” class=”widefat” />) para que o usuário possa informar a quantidade de posts que devem aparecer em seu widget.

Voltando para a linha 7, analizo se o formulário foi enviado, checando se o campo oculto foi informado, então valido o dado recebido do formulário ($opcoes['quantidade'] = (int) $_POST['quantidade_de_posts_mais_quentes']) e, finalmente, salvo as informações no banco (update_option(‘posts_mais_quentes’, $opcoes)). Notem também que as informações desse widget foram salvas como array, assim é possível armazenar todas as configurações em um único local, poupando quantidade de acesso ao banco e organizando os dados.

Tentei montar esse formulário da forma mais simples possível, além disso coloquei alguns comentários para facilitar o entendimento.

Mas não é só isso, depois de salvar as configurações desse widget ainda falta carregá-las na hora de montar o widget:

function posts_mais_quentes($args)
{
  global $wpdb;

  // Carregar as opções desse widget
  $opcoes = get_option('posts_mais_quentes');

  // Recuperando os posts
  $hot_posts = $wpdb->get_results("SELECT ID, post_title, comment_count FROM {$wpdb->posts} ORDER BY comment_count DESC LIMIT {$opcoes['quantidade']}");

  // Usando o modelo de widgets do tema
  print $args['before_widget'];
  print $args['before_title'] . "Mais Quentes" . $args['after_title'];
  print "<ul>";

  // Listando os posts mais quentes
  foreach($hot_posts as $hot_post)
    print "<li><a href='" . get_permalink($hot_post->ID) . "'>{$hot_post->post_title} ({$hot_post->comment_count})</a></li>";

  print "</ul>";
  print $args['after_widget'];
}

Essa função é a mesma do post anterior com duas pequenas alterações. Uma na linha 6, onde carrego as configurações salvas e na linha 9 onde uso a quantidade de posts informadas pelo usuário para limitar a consulta (LIMIT {$opcoes['quantidade']}).

É isso… crie novas possibilidades para seus widgets, os usuários finais possuem sempre gostos diversos, simplifique a vida deles. Abaixo coloco o código completo desse estudo com uma opção a mais para a escolha do título do widget.

<?php
/*
Plugin Name: Posts mais quentes
Description: Lista posts mais comentados
Version: 0.2
Author: Marcelo Mesquita
Author URI: http://www.marcelomesquita.com/
*/

// Posts Mais Quentes
function posts_mais_quentes($args)
{
  global $wpdb;

  // Carregar as opções desse widget
  $opcoes = get_option('posts_mais_quentes');

  // Valor padrão, caso nada tenha sido informado
  if(empty($opcoes['quantidade'])) $opcoes['quantidade'] = "5";

  // Recuperando os posts
  $hot_posts = $wpdb->get_results("SELECT ID, post_title, comment_count FROM {$wpdb->posts} ORDER BY comment_count DESC LIMIT {$opcoes['quantidade']}");

  // Usando o modelo de widgets do tema
  print $args['before_widget'];
  print $args['before_title'] . $opcoes['titulo'] . $args['after_title'];
  print "<ul>";

  // Listando os posts mais quentes
  foreach($hot_posts as $hot_post)
    print "<li><a href='" . get_permalink($hot_post->ID) . "'>{$hot_post->post_title} ({$hot_post->comment_count})</a></li>";

  print "</ul>";
  print $args['after_widget'];
}

// Configurações dos Posts Mais Quentes
function configurar_posts_mais_quentes()
{
  // Inicializa as variáveis necessárias
  $opcoes = array();

  // Salvando as opções
  if($_POST['salvar_posts_mais_quentes'])
  {
    $opcoes['titulo'] = $_POST['titulo_dos_posts_mais_quentes'];
    $opcoes['quantidade'] = (int) $_POST['quantidade_de_posts_mais_quentes'];

    // Valor padrão, caso nada tenha sido informado
    if(empty($opcoes['quantidade'])) $opcoes['quantidade'] = "5";

    update_option('posts_mais_quentes', $opcoes);
  }

  // Carregar as opções desse widget
  $opcoes = get_option('posts_mais_quentes');

  // Formulário
  ?>
    <input type="hidden" name="salvar_posts_mais_quentes" value="1" />

    <p>
      <label for="titulo_dos_posts_mais_quentes">Título:</label>
      <input type="text" name="titulo_dos_posts_mais_quentes" maxlength="26" value="<?php print $opcoes['titulo']; ?>" class="widefat" />
      <label for="quantidade_de_posts_mais_quentes">Quantidade:</label>
      <input type="text" name="quantidade_de_posts_mais_quentes" maxlength="2" value="<?php print $opcoes['quantidade']; ?>" class="widefat" />
    </p>
  <?php
}

// Ativar o widget
function posts_mais_quentes_widgets()
{
  // Adicionar o widget
  register_sidebar_widget('Posts Mais Quentes', 'posts_mais_quentes');

  // Adicionar o controle ao widget
  register_widget_control('Posts Mais Quentes', 'configurar_posts_mais_quentes');
}

// Carregar o widget
add_action('widgets_init', 'posts_mais_quentes_widgets');
?>

Boa sorte!

Criando Widgets

No WordPress o sistema de widgets permite que usuários comuns ativem funcionalidades no site sem precisar, necessáriamente, entender HTML, CSS, PHP, etc. Mas para isso, esses usuários precisam que desenvolvedores se dediquem um pouco mais para tornar seus produtos (plugins, temas, etc) aptos a trabalhar dessa forma.

Para adicionar um widget, basta criar uma uma função e informar para o WP que aquela função deve ser tratada como um widget. Isso é feito da seguinte forma:

register_sidebar_widget('Nome do Widget', 'sua_funcao', 'sua_classe');

É tão simples quanto parece, o ‘Nome do Widget’ é o identificador do widget, ‘sua_funcao’ é a função que deve ser chamada quando esse widget estiver ativo e ‘sua_classe’ é opcional e se refere ao nome da classe css que deve ser inserida nesse widget.

Para que o seu widget se adeque ao tema é importante lembrar sempre de usar o modelo de widget definido no próprio tema para conter o conteúdo de sua função. Esse modelo é sempre embutido em forma de argumento na sua função, você só precisa usá-lo. Um exemplo vale mais do que mil palavras, então vejamos como ficaria:

sua_funcao($args)
{
  print $args['before_widget'];
  print $args['before_title'] . "Nome do Widget" . $args['after_title'];
  print "conteúdo de seu widget";
  print $args['after_widget'];
}

Agora que você sabe que é fácil, não tem desculpa para não utiliza-lá em seus plugins. Assim, os usuário não precisarão fazer edições no template, para usufruir dos benefícios de seus plugins, além de tornar mais simples o seu controle.

Juntando o que você aprendeu até agora sobre criar um plugin mas o que você acabou de aprender sobre criação de widget e um pouco de criatividade, já é possível fazer algumas coisas interessantes. Que tal um plugin que mostre no sidebar os posts mais quentes:

<?php
/*
Plugin Name: Posts mais quentes
Description: Lista posts mais comentados
Version: 0.1
Author: Marcelo Mesquita
Author URI: http://www.marcelomesquita.com/
*/

// Posts Mais Quentes
function posts_mais_quentes($args)
{
  global $wpdb;

  // Recuperando os posts
  $hot_posts = $wpdb->get_results("SELECT ID, post_title, comment_count FROM {$wpdb->posts} ORDER BY comment_count DESC LIMIT 5");

  // Usando o modelo de widgets do tema
  print $args['before_widget'];
  print $args['before_title'] . "Mais Quentes" . $args['after_title'];

  print "<ul>";

  // Listando os posts mais quentes
  foreach($hot_posts as $hot_post)
    print "<li><a href='" . get_permalink($hot_post->ID) . "'>{$hot_post->post_title} ({$hot_post->comment_count})</a></li>";

  print "</ul>";

  print $args['after_widget'];
}

// Ativa o sidebar
function posts_mais_quentes_widgets() {
  register_sidebar_widget('Posts Mais Quentes', 'posts_mais_quentes');
}

// Carregar o widget
add_action('widgets_init', 'posts_mais_quentes_widgets');

?>

Agora é só ativar o plugin e adicionar o widget ao sidebar para ve-lo funcionando. Colher de chá!

Agradecimentos

Obrigado ao Rômulo por corrigir o código do plugin acima.

the_thumb

Ordenando o posicionamento das imagens

Ordenando o posicionamento das imagens

Desde quando comecei a trabalhar com WP a funcionalidade mais requisitada foi sempre inserir uma imagem nas chamadas dos posts. Para isso criei uma função que puxa, do banco de dados, a primeira imagem de um post. Apartir da versão 2.6 do WP é possível ordenar as imagens do post através de um drag’n drop nas opções de galeria, como mostra a imagem ao lado, sendo assim, basta arrastar para a primeira posição a imagem que quer usar. Essa imagem não precisa necessáriamente estar sendo utilizada no conteúdo do post, apenas ter sido anexada a ele.

Para utilizar essa função, abra o arquivo functions.php do seu tema, e depois cole o código abaixo.

function the_thumb($size = "medium", $add = "")
{
  global $wpdb, $post;

  $thumb = $wpdb->get_row("SELECT ID, post_title FROM {$wpdb->posts} WHERE post_parent = {$post->ID} AND post_mime_type LIKE 'image%' ORDER BY menu_order");

  if(!empty($thumb))
  {
    $image = image_downsize($thumb->ID, $size);

    print "<img src='{$image[0]}' alt='{$thumb->post_title}' {$add} />";
  }
}

Essa função funciona como uma template tag do WordPress, basta chamá-la no local do seu tema onde você quer que a imagem apareça, opcionalmente você pode escolher o tamanho da imagem ($size) e adicionar alguns parâmetros à tag da imagem ($add), como classes, largura, altura, etc.

Acho que é mais fácil mostrando uns exemplos.

1. Mostrar a imagem no tamanho médio (padrão 300 x 300) sem nenhum dado adicional:

<?php the_thumb('medium'); ?>

Resultaria em:

<img src='http://seusite.com/caminho/da/imagem-300x300.jpg' alt='titulo-da-imagem' />

2. Carregar uma miniatura da imagem (padrão 150 x 150) com a classe ‘alignleft’:

<?php the_thumb('thumbnail', 'class="alignleft"'); ?>

Retornaria:

<img src='http://seusite.com/caminho/da/imagem-150x150.jpg' alt='titulo-da-imagem' class='alignleft' />

3. Forçar uma imagem média a um tamanho diferente:

<?php the_thumb('medium', 'width="300" height="275"'); ?>

Apresentaria:

<img src='http://seusite.com/caminho/da/imagem-300x300.jpg' alt='titulo-da-imagem' width='300' height='275' />

Notem que forçando um tamanho para uma imagem apenas altera seu tamanho via html, o que pode distorcer a imagem se não for usado proporcionalmente.

Tela de configuração de mídia

Tela de configuração de mídia

Também é importante lembrar que é possível definir o tamanho das imagens nas configurações do WordPress, para isso vá em ‘Configurações > Mídia’ e altere as medidas a seu gosto.

Esses dias vi um artigo no wprecipes que mostrava como pegar a primeira imagem de um post e mostra-la, o problema da função deles é que ela exige que a imagem esteja no conteúdo do post o que muitas vezes não é interessante, primeiro pois força o autor a usar uma imagem no conteúdo e segundo por que a imagem que aparece na chamada tem sempre que ser a primeira que aparece no post.

Criando um plugin

Os plugins são funcionalidades extras que podem ser agregadas ao sistema padrão. O ideal é que os plugins funcionem sem realizar alterações na base do sistema (hacks), assim os usuários não ficam reféns dos plugins e quando surgirem atualizações do sistema base o usuário poderá realizá-las sem perigo de perder seus dados ou deixar seu site fora do ar.

No WordPress, os plugins ficam na pasta ‘wp-config/plugins/’. O WordPress lê o início de todos os arquivos nessa pasta a procura dos indicadores de plugin, que são algumas palavras-chave informadas em forma de comentário. Segue o formato básico das informações de um plugin:

<?php
/*
Plugin Name: Nome do plugin
Plugin URI: http://endereco.do.plugin/
Description: Descrição do plugin
Version: Versão do plugin, ex.: 1.0
Author: Nome do autor do plugin
Author URI: http://endereco.do.autor/
*/
?>

Todas essas informações devem estar no início do arquivo de seu plugin para que o WordPress os reconheça e os adicione ao gerenciador de plugins. Ao ativar um plugin o WordPress simplesmente adiciona o arquivo à lista de inclusões e a partir daí é que seu plugin começa a trabalhar.

Um plugin pode trabalhar de diversas formas, ele pode ser apenas uma função que precisa de uma chamada num tema para que funcione, ou filtrar alguma informação passada automaticamente pelo WP, ou salvar outros dados, ou tantas outras utilidades.

Hooks

Cada coisa a seu tempo, vamos começar com algo simples: como interagir com o WordPress sem hackea-lo (alterar seu núcleo). Usemos como exemplo o plugin ‘Hello Dolly’, que vem por padrão nas instalações do WP. Esse plugin mostra, no topo da área administrativa, uma mensagem randômica a cada navegação.

Mas como fazer para adicionar um texto na área administrativa do WordPress sem mexer no código do WordPress?
O que acontece é que em diversos pontos-chave do sistema existem ‘ganchos’ (hooks). Quando deparado com esses ganchos o WordPress interrompe seu processamento e verifica se existe alguma(s) função(ões) que usa(m) esse gancho para fazer alguma coisa. Caso exista, a(s) função(ões) é(são) executada(s) antes do WP voltar ao seu processamento normal.

Existem dois tipos de gancho: o ‘action’ que chama a função em determinado ponto; e o ‘filter’ que passa para a função um conteúdo como argumento, assim a função pode usar esse conteúdo para realizar sua tarefa.

Actions

O plugin ‘Hello Dolly’ usa ‘add_action(‘admin_footer’, ‘hello_dolly’)', dessa formam quando o WordPress chega no gancho ‘admin_footer’, a função ‘hello_dolly’ é chamada e carrega o texto aleatório.

Filters

Diferente do ‘action’, o ‘filter’ é usado para modificar conteúdos, por exemplo, se você quer destacar seu nome no conteúdo de seus posts, adicione um filtro ‘add_filter(‘the_content’, ‘sua_funcao’)', onde ‘sua_funcao’ varre o conteúdo e adiciona negrito as ocorrencias de seu nome. É importante que a função usada nos filtros sempre retorne o valor processado, caso contrário o conteúdo original será restaurado.

Para resumir segue um exemplo de um plugin que corrige as ocorrências de ‘wordpress’ para ‘WordPress’ no conteúdo dos posts:

<?php
  /*
  Plugin Name: Corretor WP
  Description: Corrige todas as ocorrências de 'wordpress' para 'WordPress' no conteúdo dos posts
  Version: 0.1
  Author: Marcelo Mesquita
  Author URI: http://marcelomesquita.com/
  */

  function corrige_WP($content)
  {
    $content_corrigido = str_replace('wordpress', 'WordPress', $content);

    return $content_corrigido;
  }

  add_filter('the_content', 'corrige_WP');

?>

Para saber mais sobre Hooks visite a API dos Plugin do WordPress.

Modelo de Banco do WordPress MU 2.7

Estou disponibilizando agora o modelo de banco de dados do WPMU 2.7, assim como o modelo do WordPress, esse não é uma representação fiel do banco e sim uma visualização simplificada para consulta. As tabelas dentro da área azul são as que se repetem para cada blog, onde o x é o id numério de cada blog.

No arquivo estão o xml para edição no DBDesigner e uma imagem no formato png, conforme a apresentada abaixo.

wpmu-271

Evitando posts repetidos

Quando começamos a trabalhar com Múltiplos Loops, um detalhe importante, muito bem lembrado pelo David, é quanto aos posts repetidos. É possível que os diferentes Loops tenham algum post em comum e esse post acabe sendo duplicado em algum momento.

Para evitar que isso aconteça, existe uma solução simples, a instrução ‘continue‘ do php. Essa instrução pula a iteração atual dentro de uma estrutura de loop, no nosso caso o ‘while‘. Mas antes precisamos saber quais iterações devem ser puladas, portanto criamos um array para armazenar o ‘id’ dos posts que já foram apresentados e em seguida filtramos esses posts. Com isso teremos:

<?php $usados = array(); ?>
<?php $noticias = new WP_Query("category_name=noticias&showposts=3"); ?>
<?php while($noticias->have_posts()) : $noticias->the_post(); ?>
 <?php array_push($useds, $post->ID); ?>
trecho da interface a ser repetido...
<?php endwhile; ?>
 
<?php $artigos = new WP_Query("category_name=artigosamp;showposts=3"); ?>
<?php while($artigos->have_posts()) : $artigos->the_post(); ?>
<?php if(in_array($post->ID, $usados)) continue; ?>
 <?php array_push($useds, $post->ID); ?>
trecho da interface a ser repetido...
<?php endwhile; ?>

Explicando os trechos destacados: antes de tudo, criamos um array de nome $usados. No primeiro loop, a cada iteração, adicionamos o id do post da vez no array. E finalmente, nos loops consecutivos, verificamos se o post da vez já foi usado antes de carregar o seu conteúdo.

No bom programês, seria algo como:

<?php $usados = lista(); ?>
<?php $noticias = consulte_posts("quantidade_de_posts=3 e categoria_de_nome=noticias"); ?>
<?php enquanto(houverem_posts_em_noticias()) : carregue_o_post_da_vez(); ?>
 <?php adicionar_na_lista_dos_usados($id_do_post); ?>
trecho da interface a ser repetido...
<?php verifique_se_ainda_há_posts; ?>
 
<?php $artigos = consulte_posts("quantidade_de_posts=3 e categoria_de_nome=artigos"); ?>
<?php enquanto(houverem_posts_em_artigos()) : carregue_o_post_da_vez(); ?>
<?php se(na_lista_dos_usados_houver($id_do_post)) pular_iteração; ?>
 <?php adicionar_na_lista_dos_usados($id_do_post); ?>
trecho da interface a ser repetido...
<?php verifique_se_ainda_há_posts; ?>

Caso seu template tenha mais de dois loops, basta repetir a estrutura do segundo loop.

Qualquer dúvida é só avisar.

Tema: Painter

Da necessidade de personalização rápida de um tema e suas funcionalidades, surgiu a idéia do “Painter”. Um tema simples, com cores sólidas e poucas imagens, porém altamente customizável.

custom-colorsPersonalização

Destaco nele a possibilidade de personalização através da área administrativa, permitindo a escolha das cores de cada item do site além da imagem do cabeçalho. Conta com o farbtastic, um plugin em jquery para seleção de cores, presente na versão 2.7 do WordPress, dessa forma qualquer um pode alterar o tema, mesmo sem conhecimentos em html e css.

Devido a quantidade de campos editáveis, foi inserido um select com alguns esquemas de cores pré-definidos, mas isso não impede que as cores sejam alteradas uma por uma. E para aqueles que não dispensam um editor de imagens, os campos também podem ser preenchidos manualmente.

O tema já está pronto para utilização de widgets e para os plugins lead_manager, breadcrumb-xt e authimage.

Internacionalização

O idioma padrão do tema é inglês. Junto com o tema vão os arquivos de tradução (.po e .mo) para o português Brasileiro. Assim é possível traduzir o tema para outros idiomas também.

Agradecimentos

Muito obrigado ao Fabiano Rangel que deu uma geral no tema acabando com os tons de cinza e adicionando algumas imagens, além de criar os esquemas de cores pré-definidos que poupará o tempo de muitos. Agradeço também a paciência que o Fabiano teve para entender, testar e definir as cores para a criação do plugin, se não fosse por ele vocês teriam que se virar com nomes como: “Cor de fundo clara”, “Cor de frente escura”, “Cor de frente média”, etc…

Download

painter

Exemplos

painterpainter-redpainter-pastel