Как написать свой модуль для Drupal?

Несмотря на огромное количество модулей для Drupal, всегда найдутся еще не реализованные идеи. О том как их реализовать в виде модуля для Drupal, мы сегодня и поговорим.

Для того что бы Drupal отобразил ваш модуль на странице modules, необходимо создать папку с названием модуля в /sites/all/modules (можно закинуть еще в пару мест, но об этом не сегодня), и создать внутри 2 файла - имямодуля.info и имямодуля.module. В первом будет информация о модуле, во втором код модуля.

Сегодня мы сделаем модуль-пример, который создаст страницу с настройками, а так же блок, в котором будет выводить Тиц, PR и Alexa rank сайта. Назовем его seoblock.

Для начала создаем папку seoblock в /sites/all/modules и там 2 файла seoblock.info и seoblock.module.

module-drupal-1.png

Внутренности файла инфо выглядят так:

Код
; $Id$ name = Seoblock description = Display info about site core = 6.x
Разберем каждую строку поподробнее:
Код
; $Id$
Эта строка нас не интересует. Если вы будете заливать свой модуль на drupal org, сюда автоматом вставится информация о модуле.

name (Обязательное) Имя модуля, которое будет отображаться в списке.

description (Обязательное) Описание модуля.

core (Обязательное) Поддерживаемая версия ядра.

dependencies (Не обязательное) Список модулей, необходимых для работы нашего. Например:

Код
dependencies[] = taxonomy dependencies[] = comment

package (Не обязательное) К какому пакету относить модуль. То есть, если вы хотите что бы ваш модуль отображался в списке CCK, то нужно добавить строку: package = "CCK" Если ничего не заданно, то модуль отображается в группе «Other».

Не забываем что файлы должны быть в кодировке utf-8.

На данный момент уже можно установить модуль, но он пока ничего не делает. Перейдем к файлу .module.

По большей части, модуль Drupal состоит из хуков (hook — слово страшное, но на деле все проще чем кажется), специальных функций, каждая из которых предназначена для конкретной задачи. Например, hook_perm — определяет права доступа, hook_help — создает страницу помощи, hook_block — добавляет блок. Хуков много, но нам понадобится всего несколько. Список хуков и информацию о них вы найдете на сайте api.drupal.org, - мегополезный ресурс.

Вернемся к модулю, первым из хуков у нас идет hook_help, который мы уже упоминали чуть выше.

Код
function seoblock_help($path, $arg) { $output = ''; switch ($path) { case "admin/help#seoblock": $output = '<p>'. t("Displays information about site") .'</p>'; break; } return $output; } // function seoblock_help

Слово hook в названии модуля заменено на название модуля, это стандартно для друпал, как в программировании, так и в темизировании (только в темизировании заменяется слово theme, и заменить его можно не только на название темы, но и на название движка темы).

Вторым хуком идет hook_perm.

Код
function seoblock_perm() { return array('access seoblock content', 'access administration pages'); } // function seoblock_perm()
Он задает разрешения (Permissions) для модуля. Если вы хотите добавить несколько прав, то их можно записать через запятую: module-drupal-2.png

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

Теперь давайте создадим страницу настроек, на которой можно будет ввести целевой сайт, и указать какие характеристики мы будем выводить. Хук hook_menu() позволяет создавать пункты меню, и в зависимости от настроек, выводить их или в меню, или на странице «Управление» (administer). Мы используем его для создания нашей странички.

Код
function seoblock_menu() { $items = array(); $items['admin/settings/seoblock'] = array( 'title' => 'seoblock module settings', //Заголовок страницы 'description' => 'Description of your seoblock settings page', //Описание 'page callback' => 'drupal_get_form', //Функция отображающая страницу, мы создаем //форму, поэтому используем системную функцию 'page arguments' => array('seoblock_admin'), //Содержимое формы 'access arguments' => array('access administration pages'), //Права доступа, если дать //анонимусам право 'access administration pages', они смогут админить наш модуль. 'type' => MENU_NORMAL_ITEM, //Нормальный пункт меню ); return $items; }

Более подробное описание можете посмотреть на api.drupal.ru.

Теперь нужно заполнить страницу, этим занимается функция seoblock_admin, которую мы вызвали в seoblock_menu:

Код
 'page arguments' => array('seoblock_admin'), 
Сама функция:
Код
function seoblock_admin() { $form = array(); $form['sitename'] = array( '#type' => 'textfield', '#title' => t('Sitename'), '#default_value' => variable_get('sitename', ''), '#size' => 20, '#maxlength' => 20, '#description' => t('without "http://"'), ); $form['alexa'] = array( '#type' => 'checkbox', '#title' => t('Display Alexa rank'), '#default_value' => variable_get('alexa', false), ); $form['tic'] = array( '#type' => 'checkbox', '#title' => t('Display Yandex.Tic'), '#default_value' => variable_get('tic', false), ); $form['pr'] = array( '#type' => 'checkbox', '#title' => t('Display Google.PR'), '#default_value' => variable_get('pr', false), ); return system_settings_form($form); }
Это всего лишь массив, в котором мы передаем параметры элементов формы. Элементов у нас 3: 'sitename' — название сайта, 'alexa' — alexa rank сайта, 'tic' — тиц сайта и 'pr' — PR сайта.

'#type' - тип элемента. '#title' - заголовок. '#default_value' — значение по умолчанию, в данном случае мы подгружаем (если оно есть) сохраненое значение. Более подробно, о работе с формами можно прочитать тут

Наконец выведем сам блок:

Код
function seoblock_block($op='list', $delta=0) { if ($op == "list") { $block = array(); $block[0]["info"] = t('seoblock'); return $block; } else if ($op == 'view') { switch ($delta) { case 0: $block_content = ''; $block['subject'] = 'seoblock'; $tic= variable_get('tic', false); //получаем настройки нашего модуля $alexa= variable_get('alexa', false); $pr= variable_get('pr', false); if ($tic or $alexa or $pr) { //Функции честно скомуниздил в интернетах -) if ($tic) $block['content'] .= 'Яндекс.Тиц: '.cy(variable_get('sitename', false)).'<br>'; if ($alexa) $block['content'] .= 'Alexa rank: '.alexa(variable_get('sitename', false)).'<br>'; if ($pr) $block['content'] .= 'Google.PR: '.getPageRank(variable_get('sitename', false)); } break; } return $block; } } // end seoblock_block
Тут нам интересен параметр $op, от него зависит, информацию какого рода возвращает функция. $op == "list" — выводит список блоков. $op == 'view' - выводит содержимое блока. Содержимое какого блока выводить, определяется по переменной $delta.

Если объединить все вместе, и установить, получим

Настройки

module-drupal-3.png

Блок

module-drupal-4.png

В следующий раз мы продолжим работу над этим модулем. Сделаем кеширование блока, и привяжем его к крону. Отделим дизайн и выкинем его в отдельный tpl.php файл, и может быть создадим отдельную страницу дублирующую наш блок. Оставайтесь на связи -)

Названия хуков ссылаются на описание в api.drupal.ru, если увидели название, кликните, и прочитайте инфу по хуку, без этого понять урок будет затруднительно.

Перво наперво, нужно загнать блок в кеш, и сделать обновление по cron'у. За работу с cron'ом отвечает hook hook_cron. Обработку данных для удобства засунем в отдельную функцию, которую назовем seoblock_data.

Код
function seoblock_cron() { seoblock_data(); }
функция предельно проста, при запуске крона, она вызывает функцию seoblock_data();
Код
function seoblock_data() { if(!$cash = cache_get('seoblock')) { $result=''; $tic= variable_get('tic', false); $alexa= variable_get('alexa', false); $pr= variable_get('pr', false); if ($tic or $alexa or $pr) { if ($tic) $result .= 'Яндекс.Тиц: '.cy(variable_get('sitename', false)).'<br>'; if ($alexa) $result .= 'Alexa rank: '.alexa(variable_get('sitename', false)).'<br>'; if ($pr) $result .= 'Google.PR: '.getPageRank(variable_get('sitename', false)); } $output=$result; cache_set("seoblock", $output, 'cache', time() + 36000); } else { $output = $cash->data; } return $output; }
Тут все интереснее. Вначале мы проверяем есть ли сохранненый кеш
Код
if(!$cash = cache_get('seoblock'))
и если есть, то помещаем его в переменную $cash. Если же кеша нет, то происходит запрос инфы
Код
$result=''; $tic= variable_get('tic', false); $alexa= variable_get('alexa', false); $pr= variable_get('pr', false); if ($tic or $alexa or $pr) { if ($tic) $result .= 'Яндекс.Тиц: '.cy(variable_get('sitename', false)).'<br>'; if ($alexa) $result .= 'Alexa rank: '.alexa(variable_get('sitename', false)).'<br>'; if ($pr) $result .= 'Google.PR: '.getPageRank(variable_get('sitename', false)); }
и помещение информации в кеш на 10 часов (параметры сайта обновляются не часто)
Код
cache_set("seoblock", $output, 'cache', time() + 36000);
функция seoblock_block тоже изменилась, если раньше мы каждый раз запрашивали инфу, то теперь вызываем функцию seoblock_data().
Код
function seoblock_block($op='list', $delta=0) { if ($op == "list") { $block = array(); $block[0]["info"] = t('seoblock'); return $block; } else if ($op == 'view') { switch ($delta) { case 0: $block['content'] = seoblock_data(); $block['subject'] = 'seoblock'; break; } return $block; } } // end seoblock_block
Следующая задача — отделить дизайн, и выкинуть его в отдельный tpl.php файл. Для этого используется hook hook_theme. Он регистрирует темизации.
Код
function seoblock_theme() { return array( 'seoblock' => array( 'arguments' => array('tic' => $tic, 'alexa' => $alexa, 'pr' => $pr), 'template' => 'seoblock', ), ); } // end seoblock_theme
в данном случае мы передаем функции 3 аргумента, и задаем файл темизации
Код
'template' => 'seoblock',

tpl.php к названию, за нас добавит drupal. Если бы данной строки не было, то пришлось добавить функцию тимизации «theme_seoblock».

В связи с разделением кода и дизайна, изменилась функция seoblock_data

Код
function seoblock_data() { if(!$cash = cache_get('seoblock')) { $result=''; $tic= variable_get('tic', false); $alexa= variable_get('alexa', false); $pr= variable_get('pr', false); if ($tic or $alexa or $pr) { if (variable_get('tic', false)) $tic = cy(variable_get('sitename', false)); if (variable_get('alexa', false)) $alexa = alexa(variable_get('sitename', false)); if (variable_get('pr', false)) $pr = getPageRank(variable_get('sitename', false)); } $output=theme('seoblock', $tic, $alexa, $pr); cache_set("seoblock", $output, 'cache', time() + 3600); } else { $output = $cash->data; } return $output; }
появился вызов
Код
theme('seoblock', $tic, $alexa, $pr);

файл seoblock.tpl.php

Код
<?php// $Id;?><?php if ($tic): ?> Яндекс.Тиц: <?php print $tic ?><br> <?php endif; ?><?php if ($alexa): ?> Alexa rank: <?php print $alexa ?><br> <?php endif; ?><?php if ($pr): ?> Google.PR: <?php print $pr ?><br> <?php endif; ?>

Урок получился небольшой, но надеюсь познавательный, оставайтесь на связи -)

2563