Мой первый плагин-виджет для WordPress

3 марта 2010

Сегодня написал свой первый плагин для WordPress. До этого на PHP не писал около года, так что строго не судите.

Плагин очень простой. Он представляет собой виджет, выводящий архив блога по месяцам в две колонки. Причиной для его написания стал тот факт, что мне не удалось сделать желаемое средствами WordPress, ровно как и с помощью CSS. Найти готовый плагин также не получилось. К тому же, всегда было интересно попробовать написать свой плагин. Сейчас виджет уже успешно используется на одном из моих «серых» блогов. А вот как он выглядит:

Выводим архив блога в две колонки

Я считаю, что такой способ отображения архива лучше традиционного, поскольку позволяет более рационально использовать место на веб-странице. Посмотрите несколько блогов и увидите сами, как много места пропадает впустую при выводе списка рубрик и архива в одну колонку.

Я назвал плагин «Two Columns Archive», скачать его можно здесь здесь. Устанавливается он очень просто — скачиваем, распаковываем в каталог с плагинами, активируем, добавляем сайдбар. В настройках можно указать заголовок виджета. Отображать число записей рядом с ссылкой на архив плагин не умеет, так как мне это функционал был без надобности и я не уверен, что кому-то он действительно нужен.

Далее я хотел бы прокомментировать исходный код плагина. В нем всего лишь ~80 строк, так что это не займет много места.

<?php
/*
Plugin Name: Two Columns Archive
Version: 1.0
Plugin URI: http://eax.me/two-columns-archive-plugin/
Description: Description - http://eax.me/two-columns-archive-plugin/
Author: Alexandr Alexeev
Author URI: http://eax.me/
*/

Здесь все просто — указываем в комментариях имя и версию плагина, описание, домашнюю страницу плагина, имя автора и url его сайта. WordPress отображает эту информацию в админке. Достаточно указать только Plugin Name.

function two_columns_archive_widget($args) {
  global $wpdb, $wp_locale;
  extract($args);

$query = "
  select
    max(post_date) as max_date,
    min(post_date) as min_date
  from "
.$wpdb->posts."
  where post_type = 'post'
    and post_status = 'publish'
"
;

Функция, отвечающая непосредственно за вывод виджета. Запрос определяет дату публикации первого и последнего поста. Неопубликованные посты не в счет.

  $res = $wpdb->get_results($query, ARRAY_A);
  $row = $res[0];

  preg_match('/^([0-9]{4})\-([0-9]{2})/', $row['max_date'], $m);
  $year = $max_year = $m[1]; $month = $max_month = $m[2];

  preg_match('/^([0-9]{4})\-([0-9]{2})/', $row['min_date'], $m);
  $min_year = $m[1]; $min_month = $m[2];

  $delta = $max_year*12 + $max_month - $min_year*12 - $min_month + 1;

Выполняем запрос, с помощью регулярных выражений определяем год и месяц публикации первого и последнего поста.

  echo $before_widget.$before_title;
  echo htmlspecialchars(get_option('two_columns_archive_title'));
  echo $after_title;

Выводим заголовок виджета. Переменные $before_widget, $before_title и $after_title были инициализированные в строке 13 функцией extract. Их значения были переданы в функцию то ли в объекте, то ли в ассоциативном массиве $args. Напрямую с этим аргументом лучше не работать, потому что не известно, как изменится API движка в будущем.

  $left = ""; $right = ""; // $site = get_option('site_url');
  $left_steps = ceil($delta / 2);
  for($i = 1; $i <= $delta; $i++) {
    // $month = sprintf("%02d", $month);
    $month_name = $wp_locale->get_month($month);
    $html = "<li><a href=\"".get_month_link($year, $month).
      "\">$month_name $year</a></li>\n";

    if($i <= $left_steps) $left .= $html;
    else $right .= $html;

    if(!--$month) {
      $month = 12; $year--;
    }
  }

Определяем html-код левой ($left) и правой ($right) колонок. Функция get_month_link возвращает пермалинк на страницу архива. Метод get_month объекта $wp_locale (класс WP_Locale) преобразует номер месяца в его название в соответствии с локалью движка.

?>
<div style="float: left;">
<ul><?php echo $left; ?></ul>
</div>
<div style="float: right; width: 50%;">
<ul><?php echo $right; ?></ul>
</div>
<div class="clear"></div>
<?
  echo $after_widget;
}

Выводим код сайдбара. Переменная $after_widget взялась оттуда же, откуда и $before_widget, $before_title, $after_title.

function two_columns_archive_control() {
  if (!empty($_REQUEST['two_columns_archive_title']))
    update_option('two_columns_archive_title', $_REQUEST['two_columns_archive_title']);
?>
  Title:
  <input type="text" name="two_columns_archive_title" value="<?php
  echo htmlspecialchars(get_option('two_columns_archive_title'))."\" />";
}

Эта функция вызывается при настройке сайдбара в разделе «Виджеты». Она выводит форму, позволяющую указать название виджета и сохраняет настройки при отправке формы администратором.

function register_two_columns_archive() {
  register_sidebar_widget('Two Columns Archive', 'two_columns_archive_widget');
  register_widget_control('Two Columns Archive', 'two_columns_archive_control' );
}

add_action('init', 'register_two_columns_archive');

?>

Функция register_two_columns_archive будет вызвана при срабатывании события init (где оно вызывается — не сложно проследить, открыв wp-config.php). Она регистрирует функции управления виджетом и его вывода, объявленные выше.

Вот собственно и весь плагин. Также я написал небольшой скрипт на Perl, позволяющий упростить написание плагина-виджета. На его создание меня подбило то обстоятельство, что при написании плагина я очень устал вводить строки типа «register_two_columns_archive». Правда было бы здорово это автоматизировать?

#!/usr/bin/perl

# gen-widget.pl script (version bug fixed!)
# (c) Alexandr A Alexeev 2010-2011 | http://eax.me/

use strict;

my $name = shift;
my $prfx = shift;

unless($name and $prfx) {
  die "Usage: $0 <name> <prfx>\n";
}

print <<EOF;
<?php
/*
Plugin Name: $name
Version: 1.0
Plugin URI: [...]
Description: [...]
Author: [...]
Author URI: [...]
*/

function ${prfx}_widget(\$args) {
  global \$wpdb, \$wp_locale;
  extract(\$args);

  echo \$before_widget.\$before_title;
  echo htmlspecialchars(get_option('${prfx}_title'));
  echo \$after_title;
  echo "<strong>$name</strong>\\n";
  echo \$after_widget;
}

function ${prfx}_control() {
  if (!empty(\$_REQUEST['${prfx}_title']))
    update_option('${prfx}_title', \$_REQUEST['${prfx}_title']);
?>
  Title:<br />
  <input type="text" name="${prfx}_title" value="<?php
  echo htmlspecialchars(get_option('${prfx}_title'))."\\" /><br />";
}

function register_$prfx() {
  register_sidebar_widget('$name', '${prfx}_widget');
  register_widget_control('$name', '${prfx}_control' );
}

add_action('init', 'register_$prfx');

?>
EOF

Использовать его очень просто — первым аргументом задается название плагина, вторым — префикс функций и полей формы. Следующая команда создаст готовый плагин-виджет. Нам остается лишь отредактировать его, чтобы он выводил то, что нужно:

./gen-widget.pl "Test Widget" test_widget > test-widget.php

Дополнение: добавил плагин в официальный каталог плагинов. Теперь его можно установить прямо из панели управления WordPress. Плагины → Добавить новый → «Two Columns Archive» → Устновить → Активировать плагин.

Метки: , , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.