Arquivo da tag: wordpress

Mostrando uma agenda do Google Calendar no seu site

ATENÇÃO: Este conteúdo foi publicado há 5 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Escrito em PHP. Pode ser usado no tema do seu WordPress. Requer CURL. Faz cache do calendário para não ter que baixá-lo sempre que alguém entra no seu site. Desenvolvido para um site que vai sair nos próximos dias. Use, modifique e distribua como quiser. (Não me responsabilizo por qualquer problema. Fiz pra um caso específico. A checagem de erros é meio porca.)

<?php
date_default_timezone_set('America/Sao_Paulo');
$events = Array();
$dom = new DOMDocument();
 
$file = "cached_calendar.xml";
 
$last = -1;
if (file_exists($file)) {
    $last = filemtime($file);
}
// Mude 3600 para o tempo (em segundos) que você quiser que o cache expire
if (time() - $last > 3600) {
    $fp = fopen($file, "w+");
    if (!$fp) {
        die();
    }
    // Substitua o e-mail do calendário do Google CodeJam pelo e-mail do seu calendário (público)
    $ch = curl_init("https://www.google.com/calendar/feeds/google.com_jqv7qt9iifsaj94cuknckrabd8%40group.calendar.google.com/public/full");
    curl_setopt($ch, CURLOPT_TIMEOUT, 50);
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_exec($ch);
    curl_close($ch);
    fclose($fp);
}
 
$dom->load($file);
$feed = $dom->getElementsByTagName("feed");
$entries = $feed->item(0)->getElementsByTagName("entry");
foreach ($entries as $entry) {
    $children = $entry->getElementsByTagName("*");
    $day = "";
    $start = "";
    $end = "";
    foreach ($children as $child) {
        switch ($child->tagName) {
        case "title":
            $title = $child->nodeValue;
            break;
        case "gd:when":
            if ($child->hasAttribute("startTime")) {
                $st = strtotime($child->getAttribute("startTime"));
                $time_to_sort = $st;
                $day = date_i18n("l, d/M", $st);
                $start = date("H:i", $st);
            }
            if ($child->hasAttribute("endTime")) {
                $et = strtotime($child->getAttribute("endTime"));
                $end = date("H:i", $et);
            }
            break;
        }
    }
    if ($title != "" && $day != "") {
        $events[] = Array(
            "time_to_sort" => $time_to_sort,
            "day" => $day,
            "start" => $start,
            "end" => $end,
            "title" => $title
        );
    }
}
function cmp($a, $b) {
    $a = $a["time_to_sort"];
    $b = $b["time_to_sort"];
    if ($a == $b) {
        return strcmp($a["title"], $b["title"]);
    }
    return ($a < $b) ? -1 : 1;
}
usort($events, "cmp");
 
$n = count($events);
if ($n > 0) {
    $lastDay = "";
    for ($i = 0; $i < $n; $i++) {
        $day = $events[$i]['day'];
        $title = $events[$i]['title'];
        $start = $events[$i]['start'];
        $end = $events[$i]['end'];
        if ($lastDay != $day) {
            if ($i != 0) {
                echo "</ul>\n\n";
            }
            echo "<h3 class="day"><span>$day</span></h3>\n";
            echo "<ul>\n";
        }
        echo "\t<li>\n";
        if ($start != "") {
            // Você pode modificar aqui para mostrar o horário de término ($end).
            echo "tt<span class="time">{$start}</span>\n";
        }
        echo "\t\t<strong>{$title}</strong>\n";
        echo "\t</li>\n";
        $lastDay = $day;
    }
    echo "</ul>\n";
} else {
    echo "<p>Nenhum evento cadastrado.</p>\n";
}
?>

WordPress plugin: Admin Anti-forget Alarm

ATENÇÃO: Este conteúdo foi publicado há 6 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

I wrote a small WordPress plugin to prevent users from publishing a post without excerpt or thumbnail, or with a too big excerpt, or with a too small thumbnail, or with an uppercase-only title.

This screenshot is showing some of the messages the plugin displays in portuguese.

For some of my websites it’s important to require the editors to fix some stuff before publishing something, and it looks like this is a useful feature for other people as well. There is even a Require Thumbnail plugin in the WordPress Plugin Directory that seems to do one of the things I’ve just implemented.

The plugin works with two different types of requirements: ths first generates errors (i.e., you can’t publish if you don’t fix it) and the second generates warnings (i.e., you will receive a message but you can proceed to publish if you really want to do that).

I thought of not releasing the plugin (because it’s written in Portuguese and you don’t have a cool interface to decide what’s required yet), but in a fashion of overstated bazaar I decided to push the code anyway (without putting in the WordPress plugin directory, of course) so that other people can collaborate if they want to. Take a look :)

Github project home page: https://github.com/tmadeira/antiforget
Git repository to clone: https://github.com/tmadeira/antiforget.git
Code (PHP): https://github.com/tmadeira/antiforget/blob/master/antiforget.php
Download: antiforget.zip (this is pre-alpha: I provide no warranty!)

Como mostrar o último post de cada categoria no WordPress?

ATENÇÃO: Este conteúdo foi publicado há 6 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

O WordPress é um dos meus programas preferidos e um dos que mais consome as madrugadas já faz alguns anos. Escrevi inúmeros temas, alguns plugins (um único genérico o suficiente para ser público) e já modifiquei algumas partes do código (embora hoje seja raro isso ser necessário).

Acho muito simples e me divirto ao programar em PHP para a web (talvez porque eu faça isso há uns dez anos). Gosto muito da forma como o WordPress é escrito e, com efeito, seu lema é Code is poetryCódigo é poesia. Sua documentação e seu código são muito didáticos e foram, assim como seus temas e as tabelas no banco de dados, evoluindo de acordo com o tempo: as atualizações sempre têm novas features e formas mais genéricas e mais elegantes de fazer as coisas.

O WordPress é um software livre usado por mais de 15% da web (um número incrível!) e tem uma comunidade que produz várias extensões (temas e plugins). Gosto tanto dele que certa vez (no final de 2007) escrevi um plugin só para ganhar uma camiseta (que é tamanho G e ainda assim uso de vez em quando).

Propaganda e blogagem a parte, me deparei com um problema interessante em um dos sites que administro com ele no último fim de semana (a gente sempre se depara com problemas interessantes no WordPress também): dado uma categoria com várias subcategorias, gostaria de mostrar um link para o último post de cada uma de suas subcategorias na página inicial.

Uma solução trivial seria fazer uma query pedindo os filhos de uma dada categoria (usando a tabela wp_term_taxonomy) e uma query por categoria para descobrir seu último post (usando as tabelas wp_posts e wp_term_relationships). Suponha (até o final desse post) que a categoria-mãe de todas as categorias que eu quero mostrar na página seja a de ID 33. Então, essa solução seria algo como:

<?php
$query = mysql_query("SELECT term_id FROM wp_term_taxonomy
                      WHERE parent = 33 AND taxonomy = 'category'");
while (list($cid) = mysql_fetch_row($query)) {
    $posts_query = mysql_query("SELECT p.ID, p.post_name, p.post_title
                                FROM wp_posts AS p,
                                     wp_term_relationships AS r
                                WHERE p.ID = r.object_ID AND r.term_taxonomy_id = '$cid'
                                ORDER BY p.post_date DESC
                                LIMIT 1");
    if (mysql_num_rows($posts_query)) {
        list($id, $permalink, $title) = mysql_fetch_row($posts_query);
        // Faça o que quiser com o post aqui
    } else {
        echo "A categoria $cid não tem posts.\n";
    }
}
?>

Não deve ser difícil de entender, mas dá pra resolver de forma ainda mais simples que essa. O WordPress é fantástico e usar as funções dele próprio é bem mais simples, genérico e resolve o problema. A função get_categories aceita um monte de parâmetros, mas só precisamos do child_of:

<?php
foreach (get_categories('child_of=33') as $cat) {
    list($post) = get_posts("numberposts=1&category={$cat->term_id}");
    // Faça o que quiser com o post aqui
}
?>

(quem entrou no post procurando a solução pro problema pode parar por aqui se não for nerd)

Porém, eu queria resolver o problema com uma única query. Achei que seria mais elegante resolver o problema todo no banco de dados sem escrever em PHP e achei que poderia ficar mais rápido. Acho que não ficou mais elegante e não faço ideia se fica mais rápido (fiquei com a impressão de que seja pior porque faço JOIN de quatro tabelas enormes), nem acho que tenha volume de dados (ainda) no site em que implementei isso pra realmente me preocupar, mas me diverti fazendo. Então segue o resultado:

SELECT p.ID AS id,
       CASE WHEN (p.post_date > DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) THEN
           p.post_title
       ELSE
           ''
       END AS title,
       GROUP_CONCAT(c.slug) AS cat
FROM wp_posts AS p
INNER JOIN
    (
        SELECT MAX(p.post_date) AS post_date, c.term_ID AS cid, COUNT(p.ID) AS count FROM
            wp_posts AS p,
            wp_term_relationships AS r,
            wp_terms AS c
        WHERE
            p.ID = r.object_ID AND
            c.term_ID = r.term_taxonomy_ID AND
            p.post_status = 'publish' AND
            p.post_type = 'post'
        GROUP BY c.term_id
    ) AS last ON p.post_date = last.post_date
INNER JOIN wp_term_relationships AS r ON p.ID = r.object_ID
INNER JOIN wp_terms AS c ON c.term_id = r.term_taxonomy_ID
INNER JOIN wp_term_taxonomy AS t ON t.term_id = r.term_taxonomy_ID
WHERE
    c.term_id = last.cid
    AND t.parent = 33
    AND t.taxonomy = 'category'
    AND p.post_status = 'publish'
    AND p.post_type = 'post'
    # AND last.count >= 3
GROUP BY p.ID ORDER BY p.post_date DESC, last.count DESC;

A query (que na verdade é duas) ordena o resultado por data, retorna o título vazio caso o post seja de mais de um mês atrás, junta as categorias (separando-as por vírgula) se um mesmo post for o último de mais de uma categoria e neste caso ordena as categorias por ordem decrescente de número de posts na mesma.

(A parte comentada seria para caso eu só quisesse mostrar o último post de categorias com três ou mais posts.)

Usei o resultado da query da seguinte forma:

$q = mysql_query($query); // $query é a string com aquele SQLzão
$print_final_li = false;
$first = true;
while ($a = mysql_fetch_array($q, MYSQL_ASSOC)) {
    echo "\t\t<li>";
    $permalink = get_permalink($a["id"]);
    $title = $a["title"];
    if ($title == "") {
        $print_final_li = true;
        echo "Veja também: ";
    } else if ($first == true) {
        echo "<a href="$permalink" title="$title">";
        echo get_the_post_thumbnail($a["id"], "home-thumbnail",
                                    Array("title" => get_the_title()));
        echo "</a> ";
        $first = false;
    }
    $cats = explode(",", $a["cat"]);
    foreach ($cats as $low) {
        $up = strtoupper($low);
        echo "<a class="cat" href="http://$low.juntos.org.br/"
                 title="Juntos! $up">$up</a> ";
    }
    if ($print_final_li) break;
    echo "<a class="post" href="$permalink" title="$title">$title</a>";
    echo "</li>\n";
}
while ($a = mysql_fetch_array($q, MYSQL_ASSOC)) {
    $cats = explode(",", $a["cat"]);
    foreach ($cats as $low) {
        $up = strtoupper($low);
        echo "<a class="cat" href="http://$low.juntos.org.br/"
                 title="Juntos! $up">$up</a> ";
    }
}
if ($print_final_li) {
    echo "</li>\n";
}

(e se você quiser vê-lo em prática, entre em juntos.org.br e procure por “Juntos pelo Brasil”)

Não ficou bonitinho? Se por um lado gostei da solução, por outro fiquei imaginando que deva ser um SQL tremendamente ingênuo e digno da minha inexperiência com grandes bancos de dados. O que você acha? Consegue pensar numa forma mais simples, mais eficiente e mais elegante de resolver o mesmo problema? Ou ao menos sem subqueries?

Acho que as relações necessárias já ficaram explícitas na query que eu escrevi, mas segue o diagrama do banco de dados do WordPress pra quem precisar:

Retrospective: new plugin for WordPress

ATENÇÃO: Este conteúdo foi publicado há 6 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

I’ve just wrote my first WordPress public plugin, that I’m licensing under GPL v3. This post is to make it public. I’m writing in English because the WordPress plugin directory asks me to provide a plugin page to host the files there and I’ll provide the URL of this post. Update: The plugin is now in the WordPress plugin directory: wordpress.org/extend/plugins/retrospective/


The website of the brazilian newspaper O Estado de São Paulo has a nice way to display news in a retrospective-style (check this screenshot or this link — Flash required).

Wouldn’t it be nice if we could display WordPress posts in our pages and categories in the same way just by using a shortcode? The possibilities are many. That’s why I wrote the Retrospective plugin for WordPress.

It has at least two advantages over the version you just saw:

  1. Does not require Flash (its implementation uses only CSS and JavaScript/jQuery)
  2. Has a option to respect the (time-)scale of the posts.

Its use is very simple. Wherever you add the shortcode [retrospective] the plugin will draw that cool retrospective. The shortcode supports several attributes:

  • count — limit the number of posts to be displayed (default = 10; use -1 to display all)
  • cat — display posts with category IDs comma-separated (default = display all posts)
  • width — the width of the timeline in pixels (default = 600)
  • delay — the time of the focus change animation in milisseconds (default = 1000)
  • scale — if set, respect the time scale in the distances between the points in the timeline (default = false)
  • image_width, image_height — the dimensions of the thumbnail images in pixels (default = 300×180)
  • image_border_size — the size of the image’s border in pixels (default = 7)
  • image_border_color — the color of the image’s border in hexa RGB (default = 000000)
  • image_margin — the space between the images (default = 5)
  • date_format — the date format in PHP format (default = d/m/Y)

For example, here is a [retrospective count=5 cat=20 image_border_color=2F5971] call:


Some screenshots

Here is a screenshot from juntos.org.br with scale=true (in the link you can see it working):

And here is a screenshot from a fresh WordPress install (TwentyEleven theme without modifications):


Customizing

Post thumbnails

For better results, I suggest always adding post thumbnails to your posts and using registered image sizes in image_width and image_height attributes.

Styling retrospectives

The generated HTML is very easy to style (but just be careful with margins and paddings, they’re set with !important attribute — I did it to try not to break with any theme). Here is a sample:

<div id="retro-uniquehash" class="retrospective">
    <!-- TIMELINE -->
    <ul class="time">
        <li rel="0"><a href="permalink" style="left:0px;"><span>date</span></a></li>
        <li rel="1"><a href="permalink" style="left:300px;"><span>date</span></a></li>
        <li rel="2"><a href="permalink" style="left:600px;"><span>date</span></a></li>
    </ul>
 
    <!-- PHOTOS -->
    <div class="photos">
        <ul>
            <li rel="0"><a href="permalink" title="title">
                <img src="file" class="wp-post-image" /></a></li>
            <li rel="1"><a href="permalink" title="title">
                <img src="file" class="wp-post-image" /></a></li>
            <li rel="2"><a href="permalink" title="title">
                <img src="file" class="wp-post-image" /></a></li>
        </ul>
    </div>
 
    <!-- POSTS -->
    <ul class="posts">
        <li rel="0"><a href="permalink" title="title"><h2>Title <span>(date)</span></h2>
            <p>Excerpt</p></a></li>
        <li rel="1"><a href="permalink" title="title"><h2>Title <span>(date)</span></h2>
            <p>Excerpt</p></a></li>
        <li rel="2"><a href="permalink" title="title"><h2>Title <span>(date)</span></h2>
            <p>Excerpt</p></a></li>
    </ul>
</div>

Styling a specific retrospective

The generated hash takes in consideration all the attributes sent to the shortcode and also how many retrospectives appeared before in the parsing of the actual page. I made it that way to allow users to set up two exactly equal retrospectives in the same page. Because of that, I don’t recommend setting styles for #retro-uniquehash. I think a reasonable solution for this issue is to make something like

<div id="something_that_makes_sense">[retrospective]</div>

when inserting the shortcode and then styling #something_that_makes_sense .retrospective.


Download

Here is the code for download:* retrospective.zip
* Warning: Please consider I’m using a bazaar approach here. Be aware that the plugin probably has a lot of bugs (and please tell me if you catch any).

I hope you enjoy it. Have fun and please let me have your feedback! :)

Problemas ao comentar?

ATENÇÃO: Este conteúdo foi publicado há 8 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Duas pessoas reportaram que este blog não está aceitando comentários. Eu acabei de testar e não tive problemas, porém acho estranho que ele esteja há cinco dias sem receber comentários (ou nem tanto, já que as pessoas também vivem fora da internet e os últimos quatro dias foram de Páscoa) e duas pessoas diferentes não conseguiram comentar.

Se você não está conseguindo comentar, favor deixar um comentário para eu investigar o problema.

No mais, estou temporariamente sem internet em casa (e espero que ela volte hoje), motivo pelo qual estou ausente na internet.

Conteúdo perdido

ATENÇÃO: Este conteúdo foi publicado há 9 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Hoje é dia 07 de fevereiro de 2009 e acabei de fazer uma burrada no servidor que ocasionou a perda de cerca de centenas de posts e milhares de comentários (de fato para “resolver o problema” usei um backup de maio de 2007). Estou salvando as páginas do cache do Google e ainda hoje republicarei os posts mais importantes. Não acho que valha a pena fazer um script para ler o cache do Google e cadastrar no banco de dados do WordPress os comentários, então eles serão perdidos.

(In)felizmente o blog não era atualizado desde junho de 2008 e portanto a perda não será tão grande. Desculpem o transtorno.

[update, 07/02/2009 às 23:35] Os 10 posts mais acessados do blog segundo o Google Analytics já estão no ar, portanto o transtorno está minimizado para o maior número de paraquedistas.

[update, 07/02/2009 às 23:55] Acabei de inserir anúncios do Adsense.

Mais uma vez, novo design!

ATENÇÃO: Este conteúdo foi publicado há 11 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Eu tenho alterado o design do meu site a cada seis meses, mas dessa vez me cansei do design anterior um pouco mais cedo e reorganizei o site agora em maio mesmo… :)

Estou usando WordPress 2.0 agora e aproveitei a mudança de design pra mudar um pouco a organização do site. Resolvi separar o blog dos artigos (clique no link aí em cima que você vai ler que tipo de coisa eu publicarei em cada seção).

O design ficou bem claro, porque não consegui juntar nenhuma outra cor com esse amarelo estranho que “roubei” do A List Apart. Sugestões para melhora são bem-vindos.

O logo ainda é o que o Cosme fez pra mim… Só modifiquei as cores.

O site agora fica ocupando toda a largura em qualquer resolução…

Espero que gostem… Por ter publicado o site meio rápido, é capaz de vocês encontrarem algum erro aqui dentro. Caso isso aconteça, me avisem!


A comissão organizadora da OBI2006 ainda não divulgou o resultado da primeira fase… Falta menos de uma semana pra segunda fase e eu ainda nem sei se vou ter que viajar para fazê-la!


[editado] Oops, me esqueci de fazer o código de publicação de comentários… Peraí, já vai! Tá OK agora…

Falta de Posts

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Viajei nesse final de semana, tô com três rascunhos no WordPress em desenvolvimento, estou acabando três sites e fazendo dois projetos. Por isso a falta de posts! :D Então resolvi só colocar aqui textos interessantes que li ultimamente…

Leia você também!

Sobre as mudanças

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Estou em Florianópolis e passarei aqui mais uma semana, o que é excelente. Agora estou na casa da minha tia, que, além de ficar do lado da praia, tem ADSL (e uma placa de rede sobrando no computador para o laptop aproveitar a internet… :))

Eu planejava postar um artigo por dia da Série Algoritmos, mas o artigo que estou escrevendo agora é a parte de algoritmos que eu considero a mais complicada (muito mais complicada que os algoritmos em si que vamos estudar depois): análise de algoritmos. E estou fazendo um esforço para deixar a parte matemática bem leve e introduzir essa matéria de maneira bem simples, por isso a demora.

Aí eu resolvi escrever um artigo inteiro só pra comentar sobre as mudanças no blog.

Leitores do meu feed, me desculpem pelas várias atualizações de ontem. Além de mudar a estrutura da página (tirando, por exemplo, os comentários da página inicial), eu estou reorganizando os artigos a partir de agora, separando-os em categorias (cada um com só uma categoria) e usando o plugin Simple Tags para a tagsonomia.

Se vocês observarem, incluí links para a validação de WAI e da Section 508 na minha sidebar. Meu site tá bem acessível com esse novo design e estrutura. :) Além disso, enviei-o para algumas galerias e por isso as visitas estão mais em alta do que já estavam antes nessa semana.

Hmmm… Para os que ainda não perceberam, troquei as antigas páginas Biografia e Portifólio por apenas uma seção, denominada Currículo. Essa mudança foi para que eu não precisasse de grandes atualizações em textos (o que é uma coisa muito chata de fazer!) e ter minhas informações profissionais separadas em um só lugar. Embora eu não tenha quase experiência alguma (quer dizer, experiência até eu tenho, mas não tenho cursos), espero que o currículo também me ajude com os negócios.

Adicionei um link para meus feeds no Bloglines também e dei uma arrumada na seção de problemas lógicos.

Espero que estejam gostando das mudanças… Agora estou me preparando para mudanças mais radicais, como transformar o site inteiro em Ajax (o que não é difícil no WordPress, mas vou esperar no mínimo esperar a série de algoritmos pra não ficar atrasado com ela)

LiveSearch no WordPress

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

O Cosme me apresentou hoje um projeto chamado LiveSearch. É uma aplicação Ajax bem simples (eu mesmo conseguiria fazer), mas uma idéia que eu ainda não havia tido.

Resolvi então implementar o negócio no meu blog e estou escrevendo esse artigo pra explicar como instalamos o LiveSearch de forma que ele funcione com o WordPress e dentro dos padrões de XHTML Strict (ele pede originalmente que utilizamos name num form e exige que o nome de um campo seja “q” ao invés do “s” do WordPress).

Então, mãos a obra!

1. livesearch.php

Para começar, você deve criar um arquivo e chamá-lo livesearch.php. O seu conteúdo deve ser:

<?php if (have_posts()) : ?>
<ul class="LSRes">
<?php while (have_posts()) : the_post(); ?>
	<li class="LSRow">
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>
<?php endwhile; ?>
</ul>
<?php endif; ?>

Para facilitar para quem quer aprender PHP, vou explicar linha por linha:

  1. Se houver posts, faça:
  2. Lista HTML
  3. Enquanto houver posts: Execute a função the_post().
  4. Item da Lista HTML
  5. Linca para o permalink do post com o texto do link = seu título.
  6. Fim do “Item da Lista HTML”
  7. Fim do “Enquanto houver posts”
  8. Fim da “Lista HTML”
  9. Fim do “Se houver posts”

Observação: As cores são só para reforçar a hierarquia.

O que este arquivo faz, portanto, é criar uma lista com o título dos posts. Essas funções são todas do WordPress (have_posts, the_title, the_permalink, etc.). Se você quisesse colocar outras coisas na lista que vai aparecer no resultado, pode colocar aí nesse arquivo.

No fim, salve esse arquivo em /wp-content/themes/SEU_TEMA/livesearch.php.

2. Redirecionar para livesearch.php se for uma pesquisa “live”

Coloque no início do arquivo /wp-content/themes/SEU_TEMA/search.php o seguinte conteúdo:

<?php if ($_GET["live"]) {
		include("livesearch.php");
		die();
	} ?>
  1. Se a query string live “existir”, faça:
  2. Inclua o arqiuvo livesearch.php nessa página.
  3. Morra!!! :D Isso significa para ele parar de executar qualquer coisa que esteja debaixo disso.
  4. Fim do “Se”

Isso serve para que possamos fazer as buscas de duas maneiras. Uma é a busca normal, que é acessada por /?s=queries e outra é a live que será acessada por /?live=1&s=queries (ou seja, a mesma coisa mas dando valor à variável “live”).

3. JavaScripts

Baixe o arquivo livesearch.js e coloque-o na pasta /wp-content/themes/SEU_TEMA/.

Agora faremos uma série de mudanças pra manter o negócio nos padrões web… Substitua as seguintes linhas pelo texto que aparece depois do seu número:

  • 122: if (liveSearchLast != document.getElementBy(‘livesearch’).value) {
  • 126: if ( document.getElementById(‘livesearch’).value == “”) {
  • 136: liveSearchReq.open(“GET”, liveSearchRoot + “/?live=1&s=” + document.getElementById(‘livesearch’).value + liveSearchParams2);
  • 137: livesearchLast = document.getElementById(“livesearch”).value;

Isso serve para ele não depender do nome do formulário e da query, mas somente do ID do campo do formulário e para ele abrir no xmlHttpRequest /?live=1&s=QUERY ao invés do padrão /livesearch.php?q=QUERY.

4. Eventos JavaScript nos documentos

No seu arquivo /wp-content/themes/SEU_TEMA/header.php, adicione o evento onload à tag BODY:

<body onload="liveSearchInit()">

No mesmo arquivo, dentro da tag HEAD linke para o script:

<script type="text/javascript" src="/wp-content/themes/SEUTEMA/livesearch.js"></script>

Agora, no arquivo /wp-content/themes/SEU_TEMA/searchform.php, adicione um evento onsubmit ao FORM

<form onsubmit="return liveSearchSubmit()" ...

E, no mesmo arquivo, adicione um evento onKeyPress ao INPUT e também um id:

<input id="livesearch" onKeyPress="liveSearchStart();"

E ao final desse arquivo, coloque:

<div id="LSResult" style="display: none;">
<div id="LSShadow">
</div>
</div>

Se você fez tudo certo e eu não errei aqui no tutorial, o seu script deve sair funcionando! Agora personalize usando estilos pra fazer um negócio bonito! (algo que eu não fiz porque tô pra trocar totalmente o design do meu site)


A Lógica do Negócio

O arquivo search.php recebe todas as buscas. O que eu fiz criando o livesearch.php foi formatar o resultado da busca de forma diferente para ele aparecer ali debaixo do formulário de busca.

O script é bem simples. Um Ajax que simplesmente faz um xmlHttpRequest a cada keypress do cara no campo. Aliás, acho que dá pra fazer um script bem menor pra só fazer isso.

Deixei o meu site meio feio com isso aí (uma lista de bullets normais e tal…), mas é porque eu tô pra trocar o design em breve e aí vou arrumar isso tudo! (inclusive, devo colocar mais Ajax!)

Qualquer dúvida, comente ou me mande um e-mail.