Часть первая (ознакомительная)
Не все знают, что в последних версиях второй линейки SMF появился ряд полезных (как для авторов модов, так и для администраторов форумов) функций, основная цель которых — уменьшить количество проблем при установке/удалении модов (когда моды вносят изменения в одни и те же файлы и в одни и те же места, проблемы неизбежны).
Более полную информацию об этих новых функциях можно найти в wiki-документации. Называются они хуками. К сожалению, там описаны далеко не все реализованные хуки (но в будущем ситуация должна измениться).
Рассмотрим несколько новых хуков на примере Quick Spoiler. Этот мод добавляет кнопку в редактор, для вставки в сообщения пары тегов:
code:
[spoiler][/spoiler]
Итак, прежде всего заглянем в архив мода и обратим внимание, что там нет привычного файла install.xml (или modification.xml). Там вообще из привычных *.xml файлов остался только package-info.xml, в котором прописана процедура установки. В частности, в нем указано, что при установке (и удалении) мода нужно запустить файл hooks.php. Откроем этот файл.
Наблюдаем следующую запись
code:
$hooks = array(
'integrate_pre_include' => '$boarddir/Sources/Subs-QuickSpoiler.php',
'integrate_bbc_codes' => 'spoiler_bbc_add_code',
'integrate_bbc_buttons' => 'spoiler_bbc_add_button',
'integrate_general_mod_settings' => 'spoiler_settings'
);
if (!empty($context['uninstalling']))
$call = 'remove_integration_function';
else
$call = 'add_integration_function';
foreach ($hooks as $hook => $function)
$call($hook, $function);
'integrate_pre_include' => '$boarddir/Sources/Subs-QuickSpoiler.php',
'integrate_bbc_codes' => 'spoiler_bbc_add_code',
'integrate_bbc_buttons' => 'spoiler_bbc_add_button',
'integrate_general_mod_settings' => 'spoiler_settings'
);
if (!empty($context['uninstalling']))
$call = 'remove_integration_function';
else
$call = 'add_integration_function';
foreach ($hooks as $hook => $function)
$call($hook, $function);
Это и есть хуки. Функция add_integration_function обходит массив $hooks и добавляет указанные значения в соответствующие переменные. Например, переменной $modSettings['integrate_bbc_codes'] будет присвоено значение spoiler_bbc_add_code, а переменной $modSettings['integrate_bbc_buttons'] — spoiler_bbc_add_button. При удалении мода [if (!empty($context['uninstalling']))] эти значения из переменных удаляются.
Хук integrate_pre_include обрабатывается в Load.php и содержит в себе путь к файлу, который необходимо подключить после установки мода. Раньше, без этого хука, для подключения нужного файла приходилось прописывать строчку require_once('путь к файлу') в index.php (тем самым внося изменения в один из ключевых файлов форума) — причем делать это после каждого обновления форума. Теперь же путь будет храниться в базе данных, а подключаемый файл может содержать внутри любые ваши функции.
Продолжаем изучение package-info.xml. Как видим, при установке в директорию /Sources распаковывается файл Subs-SimpleSpoiler.php. Наши функции, которые вызываются в остальных хуках, описаны именно в этом файле: spoiler_bbc_add_code, spoiler_bbc_add_button и spoiler_settings.
Конструкция в начале файла Subs-QuickSpoiler.php
code:
if (!defined('SMF'))
die('Hacking attempt...');
die('Hacking attempt...');
обязательна, так как не даёт запустить файл напрямую, минуя SMF. Не забывайте её использовать в своих проектах.
В функции spoiler_bbc_add_code через хук integrate_bbc_codes добавляем нужные нам теги (в данном случае: [spoiler][/spoiler]):
code:
$codes[] = array(
'tag' => 'spoiler',
'before' => '<div class="sp-wrap"><div class="sp-body" title="' . $txt['quick_spoiler'] . '">',
'after' => '</div></div>',
'block_level' => true,
);
$codes[] = array(
'tag' => 'spoiler',
'type' => 'unparsed_equals',
'before' => '<div class="sp-wrap"><div class="sp-body" title="$1">',
'after' => '</div></div>',
'block_level' => true,
);
'tag' => 'spoiler',
'before' => '<div class="sp-wrap"><div class="sp-body" title="' . $txt['quick_spoiler'] . '">',
'after' => '</div></div>',
'block_level' => true,
);
$codes[] = array(
'tag' => 'spoiler',
'type' => 'unparsed_equals',
'before' => '<div class="sp-wrap"><div class="sp-body" title="$1">',
'after' => '</div></div>',
'block_level' => true,
);
Здесь же происходит вызов другой функции, в которой подключаются таблица стилей и скрипты, необходимые для работы спойлера:
code:
spoiler_header();
Функция spoiler_bbc_add_button через хук integrate_bbc_buttons предоставляет возможность добавить новую кнопку, для вставки наших тегов:
code:
function spoiler_bbc_add_button($buttons)
{
global $txt;
$buttons[count($buttons) - 1][] = array(
'image' => 'spoiler',
'code' => 'spoiler',
'before' => '[spoiler]',
'after' => '[/spoiler]',
'description' => $txt['quick_spoiler'],
);
}
{
global $txt;
$buttons[count($buttons) - 1][] = array(
'image' => 'spoiler',
'code' => 'spoiler',
'before' => '[spoiler]',
'after' => '[/spoiler]',
'description' => $txt['quick_spoiler'],
);
}
В конце файла видим небольшую функцию spoiler_settings, которая подключается через хук integrate_general_mod_settings:
code:
function spoiler_settings($config_vars)
{
global $txt;
loadLanguage('QuickSpoiler');
$config_vars[] = array('select', 'qs_hide_img', explode('|', &$txt['qs_hide_select']));
$config_vars[] = array('check', 'qs_fancy');
}
{
global $txt;
loadLanguage('QuickSpoiler');
$config_vars[] = array('select', 'qs_hide_img', explode('|', &$txt['qs_hide_select']));
$config_vars[] = array('check', 'qs_fancy');
}
Это ни что иное, как добавление настроек мода в раздел Настройки модификаций. То есть при установке даже не потребуется редактировать файл ManageSettings.php, как это делалось раньше. Обратите внимание: все текстовые переменные хранятся в отдельном файле, который подключается через функцию loadLanguage.
Кстати, названия ваших функций могут быть любыми. Лишь бы они вызывались через нужные хуки.
Таким образом, при очередном обновлении форума вам даже не потребуется переустанавливать этот мод — всё будет подключаться автоматически, при наличии нужных записей в переменных $modSettings. При установке других подобных модов, использующих те же хуки, значения этих переменных не обнуляются, а дополняются, через запятую. Главное, чтоб названия пользовательских функций не совпадали. Единственное, что может потребоваться сделать — закинуть файлик spoiler.gif в директорию images каждой темы оформления, которую вы захотите добавить позже.