
Здравствуйте, друзья!
Сегодня мы с вами постараемся создать модуль для Drupal 7, который может пригодится при интеграции вашего сайта на Drupal с биржей ссылок Sape.
Мы здесь преследуем двойную цель.
Во-первых, и, пожалуй, это основная наша задача, мы постараемся научиться создавать модули для Drupal 7.
Пока что это будет простенький модуль, не делающий ничего сверхъестественного и, возможно, не использующий все великолепие хуков Drupal, но тем не менее это будет настоящий модуль, с инсталляцией и разделом настройки. Так что расценивайте его как хороший способ попрактиковаться в разработке под Drupal 7.
Во-вторых, практически каждый веб-мастер приходит в итоге к необходимости монетизации своих проектов, а некоторые ставят заработок на первое место, создают множество сайтов-сателлитов и внедряют их в биржи ссылок.
Друпал прекрасно подходит для создания сателитов, т.к. имеет большое количество готовых шаблонов и seo-инструменты (правда, для этого нужно доустановить новые модули).
Но некоторых вещей в нем все же не хватает. Для того чтобы было понятно о чем идет речь, нам придется немного отклониться от темы и поговорить о принципах монетизации сайтов.
Sape - это всем известная биржа ссылок, позволяющая вебмастерам (владельцам сайтов) с одной стороны и seo-оптимизаторам с другой стороны продавать и покупать ссылки на сайты.
Для того, чтобы ваш сайт был принят в Sape нужно лишь не нарушать законодательство РФ и добиться того, чтобы большая часть страниц вашего сайта была проиндексирована Яндексом.
Цена ссылки со страницы вашего сайта зависит от нескольких факторов. Это, в первую очередь, показатели ТИЦ и PR вашего сайта, а также уровень вложенности страницы по отношению к главной. Как правило, сайты добавляемые в Sape, поначалу имеют нулевые показатели ТИЦ и PR, но ссылки-то хочется продавать подороже!
Следовательно, остается лишь наращивать количество страниц второго уровня вложенности, т.е. вложенных в главную.
Ссылки со страниц третьего уровня вложенности имеют значительно меньшую стоимость, а более глубокие уровни Sape уже не интересны.
"Ну и что здесь такого!" - воскликнете Вы. "Ведь можно просто сделать очень длинное древовидное меню на главной странице, в котором отобразить, скажем, 600 позиций каталога".
Да, такой подход имеет право на жизнь.
Но есть парочка "Но": во-первых, робот Sape не индексирует более 150 ссылок с одной страницы, а во-вторых, даже если вы сделаете меню на 150 позиций, оно займет огромный процент от всего текстового содержимого вашей страницы. А с учетом того, что сателлиты, как правило, имеют на каждой странице очень небольшой объем текстового содержимого, Ваше меню станет преобладать на странице над остальным контентом.
В итоге, с точки зрения поисковых систем, все ваши страницы станут практически идентичными, т.н. "нечеткими дублями", и для поисковых роботов они превратятся в одну страницу, что, конечно же, скажется на их индексации.
Мы создадим модуль, призванный исправить эту ситуацию.
Цель
- Модуль должен иметь страницу настроек в админке Drupal, где можно будет настроить список выводимых модулем url
- Т.к. мы делаем сателлит и о пользователе заботимся не слишком, эти url должны выводиться в виде пейджера, используя в качестве анкоров нумерацию, начиная с нуля. Таким образом, мы существенно сократим объем меню, что позволит нам избежать пессимизации со стороны поисковых систем.
- Модуль должен иметь собственный инсталятор и сам совершать необходимые изменения в базе данных Drupal при установке и удалении.
Назовем наш маленький модуль Tcompactmenu, т.к. он призван сделать из огромного меню навигации компактный блок ссылок (постраничную навигацию).
Начнем по порядку.
1. Создаем файл tcompactmenu.info
Файл .info в Drupal 7 выглядит примерно так:
name = Tcompactmenu description = Makes a compact menu that looks like a block of numbered links. dependencies[] = menu package = "Tpackage" core = 7.x version = "7.x-1.0" configure = admin/config/user-interface/tcompactmenu files[]= tcompactmenu.module
Поясним:
- name - имя модуля. Это имя будет выводится в админке Drupal на странице модулей, должно совпадать с именем файла модуля
- description - описание модуля. Описание также будет выводиться в админке Drupal рядом с именем модуля
- dependencies[] - массив зависисмостей. Здесь указывается имя модуля, без которого данный модуль не сможет функционировать.
Секций dependencies[] может быть сколько угодно.
- package - пакет, к которому относится модуль. Пакеты группируют модули внутри себя по какому-либо признаку, например по схожей функциональности. Модули, относящиеся к одному пакету, будут в админке Drupal выведены в отдельном контейнере.
- core - мажорная версия ядра Drupal, под которую разработан модуль
version - версия модуля
- configure - путь, по которому будет доступна страница настроек модуля
- files[] - массив подключаемых модулем файлов. Секций files[] может быть сколько угодно.
2. Создаем файл tcompactmenu.install
Этот файл предназначен для установки модуля на ваш Drupal сайт и удаления его из системы. Благодаря данному файлу, при первом включении вашего модуля, в базе данных Drupal создадутся необходимые для его работы таблицы, а при удалении модуля эти таблицы также будут уничожены. Кроме всего прочего, в этом файле могут быть реализованы хуки обновления модуля до старших версий.
В Drupal 7 .install файл не обязан содержать хуки hook_install и hook_unisnstall, можно лишь реализовать hook_schema, который определяет имя и структуру необходимых таблиц.
Итак, наш файл tcompactmenu.install будет иметь следующее содержимое:
function tcompactmenu_uninstall() {
cache_clear_all('tcompactmenu','cache',TRUE);
menu_rebuild();
}
Здесь мы после удаления модуля на всякий случай очищаем кэши Drupal и перестраиваем меню, чтобы ненужные уже пункты были из него удалены.
function tcompactmenu_schema() {
$schema['tcompactmenu'] = array(
'fields' => array(
'id' => array('type' => 'serial', 'not null' => TRUE),
'url' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE)
),
'primary key' => array('id'),
);
return $schema;
}
Мы пишем весьма простую, я бы даже сказал, примитивную версию модуля, поэтому для работы ему понадобится всего одна таблица, содержащая список выводимых блоком URL. В данной версии не будет предусмотрено размещение нескольких блоков пейджера. Эту функциональность можно оставить до следующих версий.
3. Создаем файл tcompactmenu.module
Наконец, мы добрались до самого важного - собственно, файл модуля. Здесь необходимо реализовать несколько хуков.
1. HOOK_menu()
function tcompactmenu_menu() {
$items = array();
$items['admin/config/user-interface/tcompactmenu'] = array(
'title' => 'Tcompactmenu',
'description' => 'Configure the Tcompactmenu.',
'page callback' => 'drupal_get_form',
'page arguments' => array('tcompactmenu_settings'),
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
//'file' => 'tcompactmenu.admin.inc',
);
return $items;
}
Этот хук возвращает массив добавляемых модулем пунктов меню.
В нашем случае, мы добавляем в раздел настройки админки Drupal, в подраздел "Пользовательский интерфейс" ссылку на редактирование настроек модуля.
Поясним, как это работает. В массив items добавляется опять же массив, содержащий настройки данного пункта меню. Ключом массива является ссылка пункта меню. Давайте разберемся, что означают элементы вложенного массива:
- title - название пункта меню
- description - описание пункта меню. То, что будет выводится на странице конфигурации под названием.
- page_callback - какая функция Drupal должна запускаться при нажатии на данный пункт меню. В нашем случае, это функция, возвращающая форму Drupal.
- page_arguments - аргументы, передаваемые вызываемой функции. Мы говорим Drupal, что он должен вернуть форму tcompactmenu_settings, содержащую настройки модуля. Форма будет описана ниже.
- access_callback - какая функция Drupal должна вызываться для определения права доступа пользователя к разделу сайта
- access_arguments - аргументы, передаваемые функции определения права доступа. В нашем случае, это уровень доступа администратора сайта.
2. HOOK_settings()
function tcompactmenu_settings() {
$form['urls'] = array(
'#title' => t('Specify a set of URLs'),
'#description' => t('URLs should be separated by commas'),
'#type' => 'textarea',
'#default_value' => _tcompactmenu_get_urls(),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save tcompactmenu settings'),
);
return $form;
}
Этот хук возвращает форму настроек модуля (помните, в HOOK_menu() мы указали эту функцию в качестве callback?)
В этой форме мы определяем 2 элемента - текстовое поле, содержащее список URL через запятую, а также кнопку отправки данных на сервер.
В массиве, описывающем текстовое поле, есть ключ #default_value. Значением этого ключа должно быть то, что мы хотим видеть в текстовом поле, когда открывается форма настроек. Мы, с помощью отдельной функции _tcompactmenu_get_urls(), возвращаем список URL из базы данных. Функцию рассмотрим чуть ниже.
Также, момент о котором стоит помнить, это локализация модуля. Хорошим тоном является пропускать весь текст выводимый на сайте, через функцию локализации с коротким именем t. Много времени это не отнимет, зато в дальнейшем сильно упростит перевод модуля на другой язык. Например, на русский.
3. Функция _tcompactmenu_get_urls()
function _tcompactmenu_get_urls(){
$select = db_select('tcompactmenu','tc');
$select->addField('tc','id');
$select->addField('tc','url');
$entries = $select->execute()->fetchAll();
$str = "";
foreach($entries as $num => $entrie){
$str.= $entrie->url.",";
}
$str = substr($str, 0, strlen($str)-1);
return trim($str);
}
Здесь, я думаю, даже пояснений особых не нужно. Функция просто достает из таблицы модуля список URL и конкатенирует ссылки через запятую.
Заметим лишь, что покусочное построение SQL запросов в Drupal 7 весьма удобная вещь.
4. HOOK_settings_submit()
function tcompactmenu_settings_submit($form, &$form_state){
$urls = $form_state['values']['urls'];
$urls_array = explode(",", $urls);
//очищаем таблицу
db_delete('tcompactmenu')->execute();
$fields = array();
foreach($urls_array as $url){
$fields['url'] = trim($url);
db_insert('tcompactmenu')->fields($fields)->execute();
}
drupal_set_message(t('The tcompactmenu settings saved'));
}
Этот хук обрабатывает данные формы tcompactmenu_settings, описанной выше. Само собой, он запускается после нажатия пользователем на кнопку сохранения данных формы.
Хук принимает два объекта - объект формы и объект состояния формы. Как раз через объект состояния формы мы можем получить все присланные формой данные. В нашем случае это отредактированный пользователем список URL. Мы разбиваем эту строку по запятым, формируем из нее массив и вставляем каждый элемент массива в нашу таблицу модуля (предварительно очистив ее).
5. HOOK_block_info()
function tcompactmenu_block_info(){
$blocks = array();
$blocks[0]['info'] = t('Tcompactmenu links block');
$blocks[0]['cache'] = DRUPAL_NO_CACHE;
return $blocks;
}
Этот небольшой хук сообщает Drupal, что наш модуль должен породить блок. Внутри хука мы формируем массив с настройками блока - описание, которое буде выводиться на странице блоков и указание не кэшировать данный блок.
6. HOOK_block_view()
function tcompactmenu_block_view($delta = '') {
$select = db_select('tcompactmenu','tc');
$select->addField('tc','id');
$select->addField('tc','url');
$entries = $select->execute()->fetchAll();
$blocks = array();
$blocks['subject'] = null;
$blocks['content'] = theme('tcompactmenu_block', array('urls' => $entries));
return $blocks;
}
Продолжаем создание модуля для Drupal. Еще не устали? Осталось совсем немного.
Данный хук позволяет темезировать наш блок. Более того, он теоретически позволяет темизировать каждый экземпляр блока, в зависимости от его порядкового номера. Для этого предназначен аргумент $delta. Но так как мы создаем несложный модуль, у нас будет всего один экземпляр блока.
Итак, внутри хука мы достали из базы данных список URL и передали этот список функции темизации theme. Это одна из самых выжных и часто используемых функций в Drupal 7, запомните ее.
Для данной функции должен быть определен хук HOOK_theme() внутри модуля. Аргументы tcompactmenu_block и array('urls' => $entries) говорят о том, что информацию о используемом файле шаблона нужно взять из элемента массива, возвращаемого HOOK_theme() с ключом tcompactmenu_block и передать в этот файл шаблона переменную $entries, причем в файле шаблона она будет доступна по имени $urls.
Предложение получилось не из простых). Советую перечитать его пару раз и осознать получше. Данная функция вернет итоговый HTML-код после процесса темизации.
8. HOOK_theme()
function tcompactmenu_theme() {
return array(
'tcompactmenu_block' => array(
'variables' => array(
'urls' => NULL
),
'file' => 'tcompactmenu.block.inc',
'template' => 'tcompactmenu-block',
)
);
}
Вот и HOOK_theme() о котором мы только что говорили. Как видите, данный хук говорит Drupal какие элементы с помощью каких шаблонов темезировать и снабжает эти шаблоны переменными. Кроме того, он подключает файлы с функциями, которые будут доступны изнутри файла шаблона, чтобы не загромождать файл шаблона кодом.
9. Файл шаблона: tcompactmenu-block.tpl.php
<div id = "tcompactmenu-pager"> <?php $curpath = "/".request_path(); //echo $curpath; exit; foreach($urls as $num => $url): ?> <span> <a class="<?php echo $url->url == $curpath ? 'active': ''; ?>" href="<?php echo $url->url; ?>"><?php echo $num+1; ?></a> <?php //echo (($num+1)%20 == 0)? "<br />" : ""; ?> </span> <?php endforeach; ?> </div>
Шаблон блока совсем простой. Внутри него мы получаем путь до текущей страницы с помощью функции Drupal 7 request_path() и выводим ссылки подряд, используя в качестве анкоров их порядковые номера. Кроме того, мы подсвечиваем ссылку, если ее URL совпадает с URL текущей страницы.
Также я привел способ вывода ссылок в несколько строк по 20 элементов в каждой строке (внутри php-комментариев).
Вот, собственно, и все, друзья. Мы с вами создали модуль для Drupal, попутно научились описывать формы, создавать блоки и использовать темизацию. Также мы умеем вносить необходимые изменения в базу данных при установке и удалении модуля.
Конечно, это лишь малюсенькая толика информации, которая вам может понадобиться при создании реального модуля, но зато она на живом примере дает почувствовать, что значит разрабатывать модули под Drupal.
P.S. Исходники модуля можно скачать тут: tcompactmenu.rar (2.85 КБ)
