Разработка модуля на примере создания блока
Прислано: i_byte
вс, 28/02/2010 - 17:53
Судя по форуму, количество людей работающих с Drupal не так уж и мало, а количество и объем русскоязычных статей о разработке модулей под Drupal оставляют желать лучшего. Поэтому решил один раз сесть, разобраться, написать русскоязычную документацию по написанию шаблона для модуля типа блок, дабы каждый раз не вгрызаться в дебри англоязычного текста.
Приведенный ниже материал является вольной интерпретацией документации с drupal.org. Попытался не обойти стороной и локализацию модуля. Подразумевается, что используется переведенный на русский "движок" Drupal. В конце теории будет приведен код простого модуля для отображения самых активных пользователей сайта на основе подсчета количества оставленных комментариев.
Любые конструктивные замечания и советы приветствуются.
Итак
Разработка модулей для Drupal 6.x на примере блока
В каталоге modules создаем каталог латиницей по имени модуля (без пробелов)
Создаем файл латиницей имямодуля.info
В файле необходимо заполнить как минимум следующие данные
; $Id$
name = Module name
description = A description of what your module does.
core = 6.xгде
; $Id$ - тег для подстановки системой контроля версий (CVS) номера версии, даты создания и автора данного файла; используется при публикации модуля на drupal.org и контроля версий
name - отображаемое имя модуля
description - коротко, в одну строку описание модуля; используется для указания администратору сайта назначения модуля; максимум 255 символов
core - определяет под какую версию написан данный модуль; не дает подключить модуль к несоответствующей версии сайта
Также допустимы следующие необязательные параметры
dependencies - описание модулей от которых зависит данный модуль; синтаксис следующей
dependencies[] = taxonomy dependencies[] = comment
package - если данный параметр присутствует, то на странице admin/build/modules модуль будет сгруппирован с другими модулями такой же категорией. Если данный параметр не указан, то модуль будет в категории 'Other' (Другое). Данный параметр помогает поместить модуль в категорию с теми пакетами, с которыми предполагает использование, что облегчает администрирование модулей. Если не уверены, не заполняйте данный параметр.
Пример категорий:
- Audio
- Bot
- CCK
- Chat
- E-Commerce
- Event
- Feed Parser
- Organic groups
- Station
- Video
- Views
- Voting (if it uses/requires VotingAPI)
Создаем файл латиницей имямодуля.module
Не забываем, что весь код внутри должен быть заключен между тегами <?php ?>
Специфические функции имеют предопределенные имена и пишутся после знака подчеркивания и имени модуля. Предположим, модуль называется firstmodule . Тогда функции будут называться firstmodule_имяфункции.
Первая функция - необязательная.
hook_help() - функция для предоставления дополнительной информации о модуле.
Заготовка для функции будет следующая.
<?php/**
* Отображение помощи и информации о модуле
* @param path адрес по которому будет отображаться помощь
* @param arg массив содержащий текущий адрес как если бы он был возвращен из arg() функции
* @return возвращаем помощь как текст
*/
function firstmodule_help($path, $arg) {
$output = ''; //определение переменной в которой будем возвращать текст
switch ($path) {
case "admin/help#firstmodule":
$output = '<p>'. t("Здесь текст помощи") .'</p>';
break;
}
return $output;
} // function firstmodule_help
?>Примечание: хотя в приведенном примере и дальше я буду использовать кириллицу в выводимом тексте, делать это в реальном коде я не советую. Используйте латиницу и английский язык. Почему? Ответ содержится в части, рассказывающей о локализации.
Следующая функция определяет какие права доступа (разрешения) доступны для модуля и обозначается hook_perm()
Данная функция не определят сами права доступа и не предоставляет их - только описывает доступные права. Как только hook_perm () определена, администратору становятся доступны разрешения для тех или иных ролей на странице Управление/Управление пользователями/Разрешения
Пример данной функции
<?php/**
* Доступные разрешения для модуля
* @return array массив доступных разрешений для модуля
*/
function firstmodule_perm() {
return array('access firstmodule content');
} // function firstmodule_perm()
?>Чтобы избежать пересечение прав между различными модулями, название разрешений должны быть уникальны. Считается хорошим тоном включать в название имя вашего модуля, например
return array('access firstmodule', 'create firstmodule', 'administer firstmodule');
В данном примере 'administer firstmodule' описывает разрешения для настройки модуля.
Определение кода обработчика для блока
<?php/**
* Шаблон для hook_block
* @param строка $op одна из "list", "view", "save" и "configure"
* @param целое $delta код для идентификации блока
* @param массив $edit только для "save" операции
**/
function firstmodule_block($op = 'list', $delta = 0, $edit = array()) {
// код модуля
} // function firstmodule_block
?>где
$op - hook_block() вызывается для выполнения 4 различных операций: "list", "view", "save", и "configure". Через переменную $op сообщается какую из операций запрашивают.
$delta - в модуле можно использовать больше одного блока для операции. Именно для определения того или иного блока и существует переменная $delta которая обычно является целым числом. Примером мультиблочного модуля может служить модуль ядра user который имеет блок для авторизации, блок отображения новых пользователей и блок отображения пользователей on-line.
Модуль управления блоками вызовет функцию hook_block() с $op='list' когда будет строить список блоков на странице управления блоками.
<?php/**
* Шаблон для hook_block
* @param строка $op одна из "list", "view", "save" и "configure"
* @param целое $delta код для идентификации блока
* @param массив $edit только для "save" операции
**/
function firstmodule_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == "list") {
// Для построения списка модулей с именем данного модуля, для admin/block страницы
$block = array();
$block[0]["info"] = t('Название модуля');
return $block;
}
} // function firstmodule_block
?>где
$block - переменная, используемая, чтобы хранить необходимые данные, прежде, чем возвратить их.
$block[0] - $block - переменная типа массив, и каждый элемент в массиве представляет один блок. "0" индекс массива - то самое значение $delta, которое можно будет использоваться в других операциях (если бы были определены множественные блоки, то использовались бы элементы массива $block [0], $block [1], $block [2], и т.д.; также необходимо было бы проверять значение $delta, которое передают в функцию для других операций).
$block[0]["info"] - массив ассоциативный и использует именованные элементы для определения тех или иных значений. В данном случае определяется то, как будет отображаться блок на странице администрирования.
Теперь пришла пора наполнить блок содержанием
Для этого вводим в код функции hook_block следующие строки
<?php
else if ($op == 'view') {
// Код для генерации наполнения блока
$query = "SELECT nid, title, created FROM {node} WHERE created >= '%d' AND created <= '%d'";
$query_result = db_query($query, $start_time, $end_time);
}?>В данном примере используется доступ к базе drupal. Для получения результата применяется функция $query_result с передачей параметров, которые подставляются вместо "тегов" %d в SQL-запросе, запрос является текстовой строкой заключенной в переменную $query. Данный запрос является "безопасным" запросом. Имя таблицы, в данном случае node, необходимо заключать в фигурные скобки {}. Заключение в скобки требуется для поддержки механизма префикса таблиц. Префиксы используются для мультисайтинга или повышения безопасности сайта, так как произвольный префикс изменяет имя таблицы и затрудняет использование SQL-инъекций. Также желательно использовать функцию db_rewrite_sql() которая позволяет определить имеет ли пользователь права на выполнение данного запроса?
Функция db_rewrite_sql() определяется как (оригинал смотрите в database.inc)
<?php
function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array())
?>где
$query - параметр для перезаписи
$primary_table - Имя или псевдоним таблицы которая имеет первичное поле для данного запроса
Типичные имена таблиц: {blocks}, {comments}, {forum}, {node}, {menu}, {term_data} or {vocabulary}. Однако, более распространено использование псевдонимов: b, c, f, n, m, t или v.
$primary_field - Имя первичного поля
$args - Массив дополнительных аргументов
возвращается - Оригинальный запрос с JOIN и WHERE с подставленными параметрами; nid перезаписан если необходимо
Таким образом, стратегия использования SQL-запроса к базе drupal следующая:
$query = db_rewrite_sql($query); $query_result = db_query($query);
Для получения данных из результата запроса обычно используют db_fetch_object(), т.е.
$data = db_fetch_object($query_result);
Пример кода ниже:
<?php// переменная для возвращения данных которые будут отображены на экране
$block_content = '';
while ($links = db_fetch_object($query_result)) {
$block_content .= l($links->title, 'node/'. $links->nid) .'<br />';
}?>Здесь функция l() создает ссылку правильного Drupal-пути, например с использованием чистых ссылок http://(sitename)/node/2 или с подстановкой переменной http://(sitename)/?q=node/2 (путь любой страницы будет "node/#", где # идентификационный номер страницы).
В завершение необходимо вернуть данные Drupal'у для вывода их на экран. Выполнить это можно соответственно нижеприведенному шаблону:
<?php // проверяем, есть ли наполнение данными
if ($block_content == '') {
// данные отсутствуют
$block['subject'] = 'Название блока';
$block['content'] = 'Извините, данные отсутствуют';
return $block;
}
// заполняем данными
$block = array();
$block['subject'] = 'Название блока';
$block['content'] = $block_content;
return $block;?>Можно использовать следующий код, чтобы не выводить блок, если данных для наполнения нету:
<?phpif ($block_content == '') {
/* Данных нет. Блок отображаться не будет */
return;
}?>При выводе данных необходимо помнить о том, что применение функции t() дает возможности перевода на другие языки, а применение классов CSS дает возможности управлять отображением содержимого блока при его эксплуатации, что особенно актуально если блок будет передаваться другим людям. Еще лучше - использовать "themeable" вывод данных.
Далее все стандартно: записываем папку с модулем в директорию modules/, затем включаем модуль на странице admin/build/modules Управление/Конструкция сайта/Модули. Если нет синтаксических ошибок, то после сохранения конфигурации вновь отобразится страница сайта. Конфигурация видимости модуля осуществляется на странице /admin/build/block Управление/Конструкция сайта/Блоки. В случае ошибки удаляем директорию с модулем.
Создание кода для управления модулем
Используя Drupal Forms API создадим функцию для определения системных параметров модуля.
<?phpfunction firstmodule_admin() {
$form = array();
$form['firstmodule_variablename'] = array(
'#type' => 'textfield',
'#title' => t('Название параметра'),
'#default_value' => variable_get('firstmodule_variablename', 3),
'#size' => 2,
'#maxlength' => 2,
'#description' => t("Описание параметра."),
'#required' => TRUE,
);
return system_settings_form($form);
}?>Вообще то, имя после префикса firstmodule_ может быть произвольным, однако всегда нужно помнить про удобочитаемость кода.
В коде:
$form - массив элементов формы согласно Drupal Forms API. Каждый элемент массива соответствует элементу формы. В данном примере это текстовое поле на два символа с максимальным количеством символов - 2, а также названием и кратким описанием.
system_settings_form() - функция на основе данных формы создаст требуемые кнопки и т.д., позаботится о сохранении значений введенных параметров. Drupal сохранит значение параметра в базе, однако, параметры должны иметь уникальное имя, для этого и существует префикс firstmodule_ .
variable_get() - получает значение параметра, число 3 в данном случае является значением по умолчанию если параметр не был установлен ранее.
Важно чтобы название элемента в определении формы и название параметра при вызове variable_get() совпадали, так как Drupal использует название элемента в массиве $form при сохранении данных формы.
'#default_value' - если значение не установлено или нажать кнопку "Установки по умолчанию", то будет принято данное значение.
'#required' => TRUE - говорит о том, что данный параметр является обязательным для заполнения.
Функция t() отвечает за корректное отображение текста какой бы язык интерфейса не был установлен для сайта.
Теперь можно модифицировать функцию hook_block() так, чтобы использовать значение параметра при запросе к базе:
<?php
$limitnum = variable_get("firstmodule_count", 3);
$query = "SELECT nid, title, created FROM {node} WHERE created >= %d AND created <= %d";
$query_result = db_query_range($query, $start_time, $end_time, 0, $limitnum);
?>В данном примере db_query_range() подставляет значения для LIMIT в запрос, в данном случае от 0 до $limitnum. Таким образом будут выбраны не все данные, а только в нужном диапазоне, например первые 3 в данном случае.
После определения функции для параметров необходимо определить функцию для добавления соответствующих пунктов меню в интерфейс Drupal. Эту задачу выполняет hook_menu(). Пример:
<?php
function firstmodule_menu() {
$items = array();
$items['admin/settings/firstmodule'] = array(
'title' => 'Заголовок пункта меню',
'description' => 'Описание пункта настроек',
'page callback' => 'drupal_get_form',
'page arguments' => array('firstmodule_admin'),
'access arguments' => array('access administration pages'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
?>Важно чтобы справа от 'page arguments' было указано имя функции, в которой описана форма для параметров модуля. В нашем случае это firstmodule_admin.
Для того, чтобы пункт меню появился в интерфейсе необходимо очистить кеш данных. Для этого переходим на страницу admin/settings/performance Управление/Настройка сайта/Производительность и нажимаем кнопку "Очистить кеш данных".
Основные необходимые функции определены, все вроде бы работает хорошо. Однако, как себя поведет модуль в случае, если вместо ожидаемого числового значения в вышеприведенном примере будет введен символ? К тому же проверка вводимых значений является хорошей практикой программирования. Для отслеживания вводимых данных можно использовать функцию с суффиксом _validate. В нашем случае функция будет выглядеть следующим образом:
<?php
function firstmodule_admin_validate($form, &$form_state) {
$variablename = $form_state['values']['firstmodule_variablename'];
if (!is_numeric($variablename)) {
form_set_error('firstmodule_variablename', t('Вы должны ввести целое число.'));
}
else if ($variablename <= 0) {
form_set_error('firstmodule_variablename', t('Значение должно быть положительным.'));
}
}
?>Теперь код обладает всеми чертами полноценного модуля, однако, все же чего-то не хватает. А именно, что очень актуально для не англоязычных проектов, поддержки различных языков.
Поддержка локализации
Основное правило: Drupal полагает, что модули и темы написаны на английском. Для написания моделей и тем, предназначенных для других языков, используется механизм локализации.
Пожалуй, самый простой способ - это заключать выводимые данные в функцию t(). Если перейти на страницу admin/build/translate Управления/Конструкция сайта/Перевод интерфейса и ввести в строке поиска часть текста, заключенного в коде модуля в функцию t(), то строка будет найдена и появится возможность задать вручную перевод для требуемого языка. Данный метод прост, но возлагает весь перевод на администратора сайта.
Также можно использовать подстановки, например:
<?php
return t('@username, welcome to my website', array('@username' => $account->name));
?>В приведенном примере @username будет заменено на значение переменной $account->name. Для подстановок можно использовать три спецсимвола: @, % и !
В случае @ вывод будет использовать check_plain() перед выводом.
Рассмотрим способ поставки локализации вместе с самим модулем. Для этого можно использовать модуль для создания шаблона трансляции на основе англоязычного модуля. Загрузить сей чудесный модуль можно по адресу http://drupal.org/project/potx
После установки модуля переходим на страницу admin/build/translate/extract Управление/Конструкция сайта/Перевод интерфейса (вкладка "Извлечь")
Раскрываем список модулей и выбираем свой модуль (что означает, что на тестовый Drupal необходимо установить модуль с английским языком). Выбираем способ извлечения: независимый от языка шаблон или ориентированный на конкретный язык. Если был предварительно произведен перевод средствами самого Drupal, то можно выгрузить в шаблон переведенный текст. После нажатия "Извлечь" получаем шаблон с расширением pot.
Для создания файлов переводов po можно использовать специальный редактор Poedit, скачать который можно по адресу http://www.poedit.net/download.php
Запускаем Poedit и выбираем Файл/Создать каталог из POT-файла, выбираем pot файл. В появившемся окне заполняем необходимые поля. Затем указываем как будет называться файл локализации, например ru.po
Перевод осуществляется путем выбора строки в верхней части программы и введения переведенного текста в нижней части.
В директории модуля создаем директорию с именем translations и записываем туда po-файл. Теперь когда модуль будет активироваться на странице управления моделями то при совпадении языка интерфейса и po-файла будет произведен импорт перевода.
Ниже, как и обещал, практический пример: модуль для отображения в блоке энного (настраивается) количества самых активных посетителей исходя из количества комментариев. Заранее приношу извинения за английский текст, встречающийся в коде - с английским у меня не очень...
Модуль назван actcomm. Первый код для файла actcomm.info
; $Id$
name = Active commentators
description = Top active commentators
core = 6.xЗатем код для actcomm.module
<?php
//функция помощи
function actcomm_help($path, $arg) {
$output = ''; //отпределяем переменную для возврата из функции
switch ($path) {
case "admin/help#actcomm":
$output = '<p>'. t("Top active commentators order by count comments desc") .'</p>';
break;
}
return $output;
} // function actcomm_help
//функция определяет какие разрешения будут достурны ролям
function firstmodule_perm() {
return array('access actcomm content');
} // actcomm_perm()
//функция вывода блока
function actcomm_block($op='list', $delta=0) {
switch ($op) {
case 'list':
// Что будет отображаться на странице управления блоками admin/block
$block = array();
$block[0]["info"] = t('Top active commentators');
return $block;
break;
case 'view':
// Создание данных блока
// переменная для контента
$block_content = '';
//переменная actcomm_topcount будет отвечать за количество отображаемых позиций, по умолчанию 3
$limitnum = variable_get("actcomm_topcount", 3);
//поскольку комментарии хранятся в отдельной таблице вместе с именами авторов, то запрос простой
//получаем имя и количество комментариев
$query = "SELECT name, count(*) as ccom FROM {comments} group by name order by ccom desc";
//определяем доступность запроса пользователю
$query = db_rewrite_sql($query, "comments");
//подставляем границы для LIMIT и получаем результат
$query_result = db_query_range($query, 0, $limitnum);
$block_content.= "<table border=0 width=80%>";
while ($row = db_fetch_object($query_result)) {
$block_content.= "<tr><td width=50%>".$row->name."</td><td>".$row->ccom."</td></tr>";
}
$block_content.= "</table>";
// проверяем наличие данных
if ($block_content == '') {
// контента нет - выводим сообщение
$block['subject'] = t('Top active commentators');
$block['content'] = t('Comments not found');
return $block;
}
//или можем не выводить блок вовсе
/*if ($block_content == '') {
// контента нет - блок не выводится
return;
} */
// заполняем данными
$block['subject'] = t('Top active commentators');
$block['content'] = $block_content;
return $block;
break;
}
} // end actcomm_block
//определяем форму для управления параметрами модуля
function actcomm_admin() {
$form = array();
$form['actcomm_topcount'] = array(
'#type' => 'textfield',
'#title' => t('Amount of top'),
'#default_value' => variable_get('actcomm_topcount', 3),
'#size' => 2,
'#maxlength' => 2,
'#description' => t("Amount top of views commentators."),
'#required' => TRUE,
);
return system_settings_form($form);
}
//встраиваем меню в интерфейс Drupal
function actcomm_menu() {
$items = array();
//важно чтобы справа от 'page arguments' было имя функции actcomm_admin
$items['admin/settings/actcomm'] = array(
'title' => 'Top commentators module settings',
'description' => 'Description of your Top commentators settings page',
'page callback' => 'drupal_get_form',
'page arguments' => array('actcomm_admin'),
'access arguments' => array('access administration pages'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
//проверяем введенные данные
function actcomm_admin_validate($form, &$form_state) {
$topcount = $form_state['values']['actcomm_topcount'];
if (!is_numeric($topcount)) {
form_set_error('actcomm_topcountp', t('You must enter an integer for the maximum number of top commentators.'));
}
else if ($topcount <= 0) {
form_set_error('actcomm_topcount', t('Maximum number of top commentators must be positive.'));
}
}
?>Вот, собственно, пока и все.
- i_byte's blog
- Для комментирования войдите или зарегистрируйтесь
Дополню с позволения автора, код который строит html лучше вынести в отдельную theme функцию, вдруг меня не устроит тот вывод, который предлагаете Вы, для построения таблиц существует функция theme_table (используйте готовое).
для определения theme функции своего модуля пишем следующее:
<?php
function mymodule_theme() {
return array(
'mymodule_function' => array(
'arguments' => array('form' => NULL),
'file' => 'mymodule.admin.inc',
),
'profile_info' => array('arguments' => array('uid' => 0)),
);
}
function theme_mymodule_function($form) {
// Какой-то код
return $output
}
function theme_profile_info() {
//аналогично
}
?>- Для комментирования войдите или зарегистрируйтесь
Да уж - основательная статья. Спасибо.
- Для комментирования войдите или зарегистрируйтесь
код который строит html лучше вынести в отдельную theme функцию
Спасибо!
Да, писать модуль для использования сторонними относительно разработчика людьми, конечно лучше так, как Вы привели.
- Для комментирования войдите или зарегистрируйтесь
Спасибо за статью! Очень полезно.
- Для комментирования войдите или зарегистрируйтесь
ТС, конечно, молодец, что не поленился написать.
Я посмотрел бегло и заметил, например, такой фрагмент:
$block_content.= "<table border=0 width=80%>";
Это, честно говоря, жесть, в нашем веке прописывать такие html атрибуты как border и width :), да еще и значения их не брать в кавычки...
Насчет создания блоков. Я бы еще добавил актуальность их кеширования с помощью cache_set, cache_get, что нужно делать почти всегда.
Судя по количеству комментов, могу сделать вывод, что статья неплохая, но, к сожалению, не популярная на этом сайте. Причины этого:
1. Большая часть людей пользуется вьюсами, сниппетами и php-фильтром в админке сайта, и не понимает, что это плохой подход.
2. Знающие люди создают блоки в своих модулях примерно так, как описано в этом топике, и для них эта статья ничего нового не несет.
- Для комментирования войдите или зарегистрируйтесь
1. Большая часть людей пользуется вьюсами, сниппетами и php-фильтром в админке сайта, и не понимает, что это плохой подход.
И чем же плох подход использования вьюсов, сниппетов?
- Для комментирования войдите или зарегистрируйтесь
И чем же плох подход использования вьюсов, сниппетов?
Вы и сами знаете все плюсы и минусы.
- Для комментирования войдите или зарегистрируйтесь
И все же? :)
Я к примеру всегда пользуюсь вьюсами, сниппетами реже, но все зависит от ситуации и самое главное никогда не считал это плохим подходом. Поэтому и спросил у Вас чем это плохо с Вашей точки зрения.
- Для комментирования войдите или зарегистрируйтесь
Поэтому и спросил у Вас чем это плохо с Вашей точки зрения.
Если брать сниппеты, то они используют PHP-фильтр, так? А он требует использование функции eval, которую не рекомендуют часто использовать сами разработчики Zend Engine (eval() is evil). Т.е. имеем накладные расходы ресурсов. Также код сниппетов хранится в БД, что вызывает лишние запросы, когда нужно проанализировать код. А в третьих, скрипты удобнее отлаживать в файлах, а не в админке. Может я еще не все причины перечислил... (сказывается ночь без сна...)
- Для комментирования войдите или зарегистрируйтесь
Если брать сниппеты, то они используют PHP-фильтр, так? А он требует использование функции eval, которую не рекомендуют часто использовать сами разработчики Zend Engine (eval() is evil). Т.е. имеем накладные расходы ресурсов. Также код сниппетов хранится в БД, что вызывает лишние запросы, когда нужно проанализировать код. А в третьих, скрипты удобнее отлаживать в файлах, а не в админке. Может я еще не все причины перечислил... (сказывается ночь без сна...)
Ну если касаться сниппетов, то я к примеру ограничиваюсь (опять же все зависит от задач) вызовом в блоке единственной функции к примеру print theme('что-то', параметры) а саму функцию описываю в своем модуле проекта, поэтому править что-то в админке у меня нет необходимости, с моей точки зрения минус сниппета в блоке - это заказчик, вот ему надо объяснять что в этом вот блоке ничего трогать не надо.
Конечно идеологически наверное правильнее писать свой hook_block на каждый чих, но очень часто возникает необходимость и в самих сниппетах к примеру:
Вам нужен блок который будет в зависимости от роли пользователя показывать то или иное содержание т.е.: аноним - счетчик liveinternet, зарегистрированный - счетчик mail.ru, модератор - счетчик rambler.ru Вы лично будете писать модуль, напишете в блоке <?php global $user и т.д... , или создадите три блока с разными счетчиками с правами показа по ролям??>
- Для комментирования войдите или зарегистрируйтесь
Вам нужен блок который будет в зависимости от роли пользователя показывать то или иное содержание т.е.: аноним - счетчик liveinternet, зарегистрированный - счетчик mail.ru, модератор - счетчик rambler.ru Вы лично будете писать модуль, напишете в блоке <?php global $user и т.д... , или создадите три блока с разными счетчиками с правами показа по ролям??>
Ну, самый простой и быстрый способ - это, конечно, создание трех блоков в админке с правами показа по ролям. Тут обходимся без пхп-фильтра.
Но в принципе, по-моему, самый оптимальный способ - это создать свой модуль my_module_block, где через один hook_block реализовывать все блоки сайта.
Хотя если все делать идеологически правильно, то на это уходит больше времени. Тут, как мне кажется, главное найти компромисс: если работа не стоит лишних усилий - найти более быстрое решение. А если труд окупается - стремиться к идеалу...
- Для комментирования войдите или зарегистрируйтесь
Хороший пример, спасибо!
Но такое ощущение, что немного сбита система наименований. Например, складывается впечатление, что actcomm_admin() - это тоже какой-то хук. А на самом деле?
- Для комментирования войдите или зарегистрируйтесь
блин у меня после подключения отключается отображение модуля Administration menu ! что за хрень? да и блок не отображается в странице блоков?!
- Для комментирования войдите или зарегистрируйтесь






Комментарии