Как добавить кнопку

Этот материал посвящен созданию произвольных кнопок для SMF: в главном меню, в разделах, в темах.

С момента публикации статьи о хуках в SMF прошло много времени. Некоторые моменты остались за кадром. Рассмотрим на новом примере.

Итак, хук — это примочка, мод, не вносящий изменений в файлы движка.

Новые функции описываются в одном файле, который выводит нужные вам данные в заданных местах форума.

Элементы главного меню

К примеру, захотели добавить кнопку в главное меню. Раньше что для этого приходилось делать? Лезть в index.template.php, искать, править... А если на форуме использовалось много тем оформления? Править index.template.php в каждой из них? Потом ситуация изменилась, править нужно было только один файл — Subs.php.

Но файл один, а количество модов, которые вносили в него изменения, с каждым днём увеличивается. И при установке каждого следующего ожидаемо возникновение проблем и ошибок. Поэтому разработчики придумали хук integrate_menu_buttons — функцию, принимающую в качестве параметра массив с кнопками меню.

Подключается так:

$hooks = array(
    'integrate_pre_include' => '$sourcedir/Subs-MyMod.php',
    'integrate_menu_buttons' => 'example_menu_buttons'
);

foreach ($hooks as $hook => $function)
    add_integration_function($hook, $function);

Сначала описывается массив с хуками, которые нам нужны, а затем этот массив прогоняется через функцию add_integration_function. После этого в таблице settings в базе данных появятся новые строчки: integrate_pre_include со значением $sourcedir/Subs-MyMod.php и integrate_menu_buttons со значением example_menu_buttons.

Файл Subs-MyMod.php разместите в папке Sources. В этом файле описывается функция example_menu_buttons.

Привыкаем к созданию отдельных подключаемых файлов, которые никуда не пропадут и не обнулятся при очередном обновлении форума — полезная практика.

Изменённый Subs-MyMod.php:

if (!defined('SMF'))
    die('Hacking attempt...');

// Изменение или добавление пунктов меню
function example_menu_buttons(&$buttons)
{
// тут весь наш код
}

Обратите внимание на начало файла. Если не хотите, чтобы форум взломали через созданный вами файл, не забывайте указывать эти строчки:

if (!defined('SMF'))
    die('Hacking attempt...');

Продолжим. Цель: добавить новую кнопку в меню. Функция example_menu_buttons принимает в качестве параметра массив $buttons, поэтому нам остается создать новый элемент в этом массиве:

$buttons['mybutton'] = array(
    'title' => $txt['mybutton_text'], // переменная с названием кнопки
    'href' => $txt['mybutton_link'], // ссылка куда-нибудь
    'show' => true, // если не хотим показывать кнопку, пишем false
    'sub_buttons' => array(), // вложенные пункты, по умолчанию отсутствуют
);

Используемые текстовые переменные — в данном случае $txt[’mybutton_text’] и $txt[’mybutton_link’] — обязательно описываем и сохраняем в языковом файле (например, в Modifications.russian-utf8.php). Так как мы работаем с хуками, то лучше и языковые файлы подключать отдельно, не трогая те, что есть. Сохраняем переменные мода в файл php, называем, как хотим (лучше, чтобы название совпадало с названием будущего мода, чтобы не запутаться), переносим в папочку languages (внутри темы default) и затем подключаем через функцию loadLanguage, там где требуется:

global $txt;

loadLanguage('MyMod');

// Добавляем новый пункт в меню
$buttons['mybutton'] = array(
    'title' => $txt['mybutton_text'], // переменная с названием кнопки
    'href' => $txt['mybutton_link'], // ссылка куда-нибудь
    'show' => true, // если не хотим показывать кнопку, пишем false
    'sub_buttons' => array(), // вложенные пункты, по умолчанию отсутствуют
);

Да, кнопочку добавили, но только выводится она в конце. А если нужен вывод после пункта «Поиск»? Можно так:

$counter = 0;
foreach ($buttons as $name => $array)
{
    $counter++;
    if ($name == 'search')
        break;
}

$buttons = array_merge(
    array_slice($buttons, 0, $counter, TRUE),
    array('mybutton' => array(
        'title' => $txt['mybutton_text'], // переменная с названием кнопки
        'href' => $txt['mybutton_link'], // ссылка куда-нибудь
        'show' => true, // если не хотим показывать кнопку, пишем false
        'sub_buttons' => array(), // вложенные пункты, по умолчанию отсутствуют
    )),
    array_slice($buttons, $counter, NULL, TRUE)
);

Своя кнопка в главном меню

Идём дальше. Требуется изменить готовые пункты меню? Например, добавим атрибут target="_blank" к кнопке «Помощь»:

$buttons['help']['href'] .= '" target="_blank';

А ещё легко добавлять вложенные пункты меню. Например, добавим подпункт «Сайт», который появляется при наведении на пункт «Начало»:

$buttons['home']['sub_buttons'] = array(
    'site' => array(
        'title' => $txt['mysite'],
        'href' => $txt['mysite_link'],
        'show' => true,
        'is_last' => true,
    )
);

Названия кнопок и ссылки рекомендую хранить в языковых файлах, а не указывать прямо в коде. Тогда в будущем (а для кого и в настоящем) вам будет очень легко, например, для каждого языка выводить отдельную ссылку: для русских mysite.ru, для англоговорящих: mysite.ru/en и т. п.

Добавляем кнопку внутри разделов

С помощью ещё одного полезного хука — integrate_messageindex_buttons — создаются кнопки на страницах разделов:

function example_messageindex_buttons(&$normal_buttons)
{
    global $txt, $scripturl, $context;

    loadLanguage('MyMod');

    $normal_buttons['new_button'] = array(
        'test' => 'can_post_new', // Проверка прав доступа (в данном примере идет проверка на возможность создавать новые темы)
        'text' => 'hook_messageindex_buttons', // Текст кнопки
        'image' => 'im_reply.gif', // Иконка
        'lang' => true,
        'custom' => 'title=""', // Всплывающая подсказка для кнопки
        'url' => $scripturl . '?action=new_action;board=' . $context['current_board'] . '.0' // Действие (URL) для кнопки, передача параметра $_GET['board']
    );
}

Остальные кнопки

Аналогично для добавления кнопок на страницах тем (хук integrate_display_buttons):

function example_display_buttons(&$normal_buttons)
{
    global $txt, $scripturl, $context;

    loadLanguage('MyMod');

    $normal_buttons['new_button'] = array(
        'test' => 'can_reply', // Проверка прав доступа (в данном примере идет проверка на возможность отвечать в теме)
        'text' => 'hook_display_buttons', // Текст кнопки
        'image' => 'im_reply.gif', // Иконка
        'lang' => true,
        'custom' => 'title=""', // Всплывающая подсказка для кнопки, используется редко
        'url' => $scripturl . '?action=new_action;topic=' . $context['current_topic'] . '.0' // Действие (URL) для кнопки, передача параметра $_GET['topic']
    );
}

Кнопка на страницах тем

Кнопки в нижней части страницы создаются так же. Только на этот раз используется хук integrate_mod_buttons, а в качестве входного параметра принимается массив $mod_buttons:

function example_mod_buttons(&$mod_buttons)
{
    global $txt, $scripturl, $context;

    loadLanguage('MyMod');

    // Обратите внимание — здесь уже используется массив $mod_buttons (а не $normal_buttons, как в двух функциях выше)
    $mod_buttons['new_button'] = array(
        'test' => 'can_delete', // Проверка прав доступа (в данном примере идет проверка на возможность удалять темы)
        'text' => 'hook_mod_buttons', // Текст кнопки
        'image' => 'im_reply.gif', // Иконка
        'lang' => true,
        'custom' => 'title="' . $txt['hook_mod_buttons_title'] . '"', // Всплывающая подсказка для кнопки
        'url' => $scripturl . '?action=new_action;topic=' . $context['current_topic'] . '.0' // Действие (URL) для кнопки, передача параметра $_GET['topic']
    );
}

Модераторская кнопочка

В качестве примера посмотрите TopicRenamer.

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

function example_messageindex_buttons()
{
    global $txt;

    loadLanguage('MyMod');

    // Выводим что-нибудь на страницах разделов
    echo '<p class="description">' . $txt['hook_echo'] . $txt['integrate_messageindex_buttons'] . '</p>';
}

Поскольку кнопок мы не изменяем и не добавляем, входной параметр (в виде массива $normal_buttons) не обязателен. А результат на скриншоте: Выводим свой текст внутри раздела

Аналогичный вывод используется на страницах тем.

В модах Zen Block и Topic Rating Bar хуки integrate_display_buttons и integrate_messageindex_buttons как раз используются нестандартным образом.

Учебный пример

Плюсануть
Поделиться
Класснуть