18 Окт 2010

XenForo: Краткий обзор архитектуры форума для программистов

Category: XenForoFractalizeR @ 00:46

В этой статье я постараюсь вкратце описать архитектуру нового форумного движка XenForo, нового конкурента VBulletin и IPB.

Размеры кода

Размер основной части кода XenForo 3,24 МБ (3 405 312 байт). Еще 8,31 МБ (8 724 429 байт) занимает Zend Framework (далее ZF), который поставляется вместе с кодом XenForo. ZF включен в поставку целиком, хотя используется из него только небольшая часть.

MVC и модель контента

XenForo полностью основан на MVC архитектуре. Есть отдельные классы для моделей, видов и контроллеров. Корневой index.php имеет размер в 467 байт и заканчивается, как и положено в таких случаях

$fc = new XenForo_FrontController(new XenForo_Dependencies_Public());
$fc->run();

Разумеется, в ходу автозагрузчик классов. Система именования классов как в ZF.

Сама MVC пока внутри использует классы ZF, но то, что XenForo_Controller не унаследован от соответствующих классов ZF, говорит о том, что эта часть, скорее всего, будет переписана.

MVC работает следующим образом. Все, что идет через index.php, обрабатывается классами XenForo_Controler_Public_*. Все, что через admin.php – XenForo_Controller_Admin_*. Соответствующий класс-обработчик выбирается исходя из префикса URL. Скажем, если запрашивается www.example.com/forum, запрос передается на обработку XenForo_ControllerPublic_Forum. Все префиксы роутинга задаются в административной панели и могут добавляться дополнениями (addons). Все классы MVC обеспечивают полный SEO из коробки (например, для каждого префикса роутинга существует соответствующий класс XenForo_Route_Prefix_*, который отвечает за красивые URL для данного префикса и за выбор контроллера для данного префикса).

Контроллер может запросить какие-то данные из модели, а потом отрисовывает вид (о шаблонах см. далее), передавая ему необходимые параметры (например, список сообщений раздела форума).

Система контента XenForo чем-то слегка напоминает Друпал. Во всяком случае, здесь тоже есть понятие Node, правда выражение «Everything is a node» здесь уже не работает.

Пока в XenForo типов контента четыре: категория (что-то вроде папки), раздел форума (в котором могут быть сообщения), страница (HTML) и ссылка (обычный редирект). Каждый тоже называется Node (узел). Причем, каждый экземпляр узла может быть предком/потомком экземпляра любого другого типа. Пока не знаю, как эта гремучая смесь, например, из страницы и дочернего ей раздела форума, будет отображаться, не пробовал :).

Некоторые типы контента можно слегка расширять. Так, например, для страницы помимо, собственно, ее HTML содержимого, которое указывается в виде шаблона XenForo) можно указать PHP обработчик, который, например, получит из БД дополнительные данные для отображения или вообще плюнет в пользователя ошибкой. PHP обработчики везде указываются не кодом на PHP, как этого можно было ожидать, а именами класса и статического метода-обработчика. При активации класс будет загружен автолоадером (соответственно, должен быть правильно расположен в файловой системе).

Типы контента пока заданы жестко, самому добавить их не получится. Даже их названия в админке почему-то не локализованы.

Модель данных делится на две половинки:

  • «модель для чтения» — классы, унаследованные от XenForo_Model; используются для удобного чтения информации из базы данных
  • «модель для записи» — классы, унаследованные от XenForo_DataWriter; используются для создания и изменения содержимого

Например, модель разделов форума состоит из XenForo_Model_Forum + XenForo_DataWriter_Forum. Хотя из этого правила есть  небольшие несимметричные исключения вроде XenForo_Model_Post + XenForo_DataWriter_DiscussionMessage_Post. Впрочем, не будем забывать, что XenForo пока еще в бете и, несмотря на то, что API уже устоялся, небольшие изменения все равно возможны.

Использование сторонних библиотек

XenForo использует Sabre и Zend Framework. Причем, наличие в коде мест, подобных

/*require_once('Zend/Loader/Autoloader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader(array($this, 'autoload'));*/

spl_autoload_register(array($this, ‘autoload’));
скорее всего, означает, что от лишних зависимостей на протяжении разработки продолжат избавляться, заменяя их на что-то свое более легковесное и более специализированное.

Из ZF используется совсем немного классов. В их числе Zend_Registry (в качестве реестра для синглтон-подобных объектов вроде экземпляра XenForo_Db), Zend_Config, Zend_Cache (много чего кеширует, в частности используется в базовом классе моделей XenForo_Model), Zend_Service_ReCaptcha, Zend_Http_Client, Zend_Mail, Zend_Validate и некоторые другие.

Для работы с базой данных используется часть комплекта Zend_DB (Zend_Db_Adapater_Abstract и подобнее), завернутая в класс XenForo_DB, что опять говорит о том, что и эту часть в последствии перепишут. Результат выполнения запроса к базе представляет собой обычный массив (как mysql_fetch_assoc, практически), так что особых проблем здесь не будет.

Конструктор запросов не используется, они встроены прямо в код, как обычно (что, конечно, несколько затруднит поддержку нескольких баз данных. Но с другой стороны, запросы сконцентрированы внутри модели, так что…)

Архитектура дополнений

Для расширения форума предназначено несколько событий, на которые можно повесить обработчики. Обработчики указываются в админке, как уже было сказано, через имя класса и метода, что позволяет использовать акселераторы вроде APC для кеширования кода дополнений. Список обработчиков вместе с базовой информацией о плагине помещается в *.xml файл. Писать его руками не обязательно. Достаточно активировать отладочный режим на форуме и в админке появятся дополнительные возможности. PHP файлы дополнения, разумеется, надо будет сначала распаковать в соответствующую папку. Классы XenForo лежат в /library/XenForo, стало быть ваши будут лежать в /library/VasyaCorp. Меня это порадовало, поскольку довольно часто я занимался поиском остатков плагина в файловой системе при его удалении из VBulletin.

Поскольку практически каждое дополнение должно иметь настройки, их можно создавать прямо в админке и экспортировать в *.xml вместе с информацией о хуках. Располагаются они там же, где и настройки самого XenForo и выглядят неотличимо. Встраивать их можно в произвольные места раздела общих настроек XenForo. Устроено все примерно также, как это было в VBulletin. Очень удобно и практически нет необходимости писать код для их поддержки (все настраивается через интерфейс), хотя, конечно, при желании дополнение может встроить свою отдельную страницу в административную панель. Это делается довольно просто. Из дополнений к настройками можно обращаться так: XenForo_Application::get(‘options’)->discussionsPerPage.

Меня немного удивило количество хуков. Я полагаю, все помнят оглушительное количество хуков в VBulletin (в версии форума 4.0.3 их было 996 и это без хуков блогов и CMS!), которое даже в голове нельзя было удержать? В XenForo хуков всего… 17! Такое количество объясняется их назначением. Вот их имена:

  • container_admin_params
  • container_public_params
  • controller_pre_dispatch
  • front_controller_post_view
  • front_controller_pre_dispatch
  • front_controller_pre_route
  • front_controller_pre_view
  • init_dependencies
  • load_class_bb_code
  • load_class_controller
  • load_class_datawriter
  • load_class_model
  • load_class_route_prefix
  • load_class_search_data
  • load_class_view
  • navigation_tabs
  • visitor_setup

Небольшая инспекция кода показала, что семейство хуков load_class_* предназначено для динамического расширения соответствующей группы классов XenForo. Вы просто пишете свой класс, расширяющий один из базовых специальных классов системы, а затем внутри хука указываете его имя. Вот и все. Методы классов XenForo спроектированы именно для такого устройства работы дополнений, поэтому пользоваться данным способом очень удобно.

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

В общем, малое число хуков, похоже, вполне компенсируется их мощью.

Система шаблонов

Как и во всех современных форумах в XenForo есть КУЧА шаблонов. Синтаксис довольно мощный (см. отрывки внизу), впрочем, этим уже никого не удивишь. Спецтеги пишутся похожим на PHPTAL («неймспейсированный» XML/HTML). Один шаблон может содержать несколько файлов. Например, шаблон forum_list содержит forum_list, node_list (он вставляется в forum_list), node_list.css, sidebar.css, sidebar_online_users. CSS в шаблоне подключается через xen:require, что позволяет кешировать все CSS файлы как угодно.

<xen:require css="node_list.css" />
<xen:if hascontent="true">
<fieldset>
    <ol class="nodeList sectionMain" id="forums">
    <xen:contentcheck>
        <xen:foreach loop="$renderedNodes" value="$node">{xen:raw $node}</xen:foreach>
    </xen:contentcheck>
    </ol>
</fieldset>
</xen:if>
-------------------------------------
<xen:edithint template="node_link.css" />
-------------------------------------
<xen:contentcheck>
    <xen:foreach loop="$onlineUsers.records" value="$user">
        <xen:if is="{$user.is_moderator} OR {$user.is_admin}">
            <li>
                <xen:avatar user="$user" size="s" img="true" />
                <a href="{xen:link members, $user}" class="username">{xen:helper richUserName, $user}</a>
                <div class="muted">{xen:helper userTitle, $user}</div>
            </li>
        </xen:if>
    </xen:foreach>
</xen:contentcheck>

Шаблоны можно вставлять друг в друга через xen:include

Обратите внимание на использование хелперов в шаблонах. Хелпер, как и в Symfony, это просто метод класса. Например, вот код хелпера helperUserLink:

public static function helperUserLink(array $user)
	{
		return '<a href="'
			. XenForo_Link::buildPublicLink('members', $user)
			. '" class="username">'
			. htmlspecialchars($user['username'])
			. '</a>';
	}

Поисковая машина

Поисковая машина в XenForo реализована в виде отдельного класса (в отличие от ненавидимой мною реализации в VB4, в которой, по-моему, сами разработчики давно уже запутались, просто не сознаются в этом), унаследованного от XenForo_Search_SourceHandler_Abstract. В настоящий момент реализация только одна — MySqlFt.php (class XenForo_Search_SourceHandler_MySqlFt extends XenForo_Search_SourceHandler_Abstract), реализация для Sphinx уже доступна дополнением от стороннего разработчика на официальном форуме.

Система локализации

Система локализации практически полностью повторяет свой аналог из VBulletin с тем исключением, что фразовые группы отсутствуют вообще. Вот начало файла фраз английского языка:

<?xml version="1.0" encoding="utf-8"?>
<phrases>
<phrase title="1_more_message" global_cache="0" version_id="1000017" version_string="1.0.0 Alpha 7"><![CDATA[1 more message]]></phrase>
<phrase title="about" global_cache="0" version_id="1000015" version_string="1.0.0 Alpha 5"><![CDATA[About]]></phrase>

Каждое дополнение может иметь собственные фразы. Языки можно экспортировать. Переводить дополнения  можно прямо в админке.

При внутренней компиляции шаблонов, фразы соответствующего языка вставляются прямо в PHP вариант, поэтому на загрузку фраз, в них использованных, время не расходуется.

Если в своем дополнении вы часто (например, при каждой загрузке часто открывающейся страницы) используете фразу вне шаблонов, можно добавить ее в глобальный кеш. Если фраза используется редко (например, сообщение о критической ошибке), ее можно непосредственно загрузить из базы данных вызовом $myPhraseString = new XenForo_Phrase(‘phrasename’).

Кстати, русская локализация XenForo уже практически готова.

Система стилей

Я не дизайнер и вообще у меня плохой вкус. Все, что касается дизайна и его разработки меня пугает. Но в XenForo мы видим древовидную систему стилей, аналогичную VB, в которой мы можем взять какой-то стиль за основу и изменить часть его настроек или шаблонов, породив дочерний стиль.

Кир с Майком реализовали самый крутой редактор CSS, который мне приходилось вообще доводилось в жизни видеть. Dreamweaver отдыхает :). В XenForo настраивается все и настраивается вполне визуально. Забудьте о редактировании CSS напрямую, о листе с двумя тысячами переменных, который какой-то нехороший человек реализовал в VB. Здесь все очень грамотно сгруппировано так, что 99% секций помещаются на одном экране. Если вы не такой лох в плане дизайна, как я и имеете художественный вкус, наверное, вы сможете уволить своего дизайнера, поскольку стиль сможете сделать и сами (через пару месяцев, как наиграетесь с редактором).

Все настройки стиля XenForo компилирует в соответствующие CSS файлы, которые подключаются по мере необходимости.

Разумеется, все настройки экспортируются и импортируются в виде *.xml файлов, так что в ближайшее время для XenForo появится большое количество стилей.

Система аутентификации

У вас есть база данных, скажем, от WordPress? Импортируйте пользователей из WP в базу XenForo с сохранением их паролей! Для того, чтобы потом все заработало, вам придется всего лишь расширить класс XenForo_Authentication_Abstract чтобы подсказать XenForo каким образом проверять пароль. Данные пользователей с вашими системами аутентификации связывает таблица xf_user_authenticate.

Службы связи

Уже достаточно давно на форумах позволяется указывать свои контакты в различных системах коммуникации типа ICQ. В XenForo существует легко расширяемая система контактных служб. Службы можно добавлять в панели управления. Класс поддержки службы выглядит примерно так:

<?php
class XenForo_Model_IdentityService_Icq extends XenForo_Model_IdentityService_Abstract
{
	protected function _getIdentityServiceId()
	{
		return 'icq';
	}
 
	static public function verifyAccountName(&$accountName, &$error)
	{
		if (!preg_match('/^\d+$/', $accountName))
		{
			$error = new XenForo_Phrase('please_enter_valid_icq_uin_using_numeric_characters_only');
			return false;
		}
 
		return true;
	}
}

Теперь уже никто не сможет ввести в поле ICQ своего профиля строчку «Продам носки шерстяные» 🙂

Система прав и привилегий

Каждая группа пользователей системы имеет права по умолчанию. Плюс права каждой группы можно дополнительно настроить в любом типе узла. Разумеется, привилегии наследуются.

Типов разрешений четыре. Inherit, Allow, Revoke, Deny. Revoke от Deny отличается исключительно тем, что если, например, в разделе форума для группы пользователей указано Deny, а в его подразделе Allow – доступ все равно будет запрещен. Deny нельзя переопределить в дочернем наборе прав. А Revoke можно. В остальном все похоже на VBulletin и другие движки.

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

$userCanCleanSpam = (XenForo_Permission::hasPermission($visitor['permissions'], 'general', 'cleanSpam'));

Что же плохого?

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

Самым большим недостатком сейчас мне показалось отсутствие шаблонных хуков. Если дополнению требуется изменять шаблоны форума, администратор должен проделать это вручную, либо разработчик должен сделать это путем str_replace / preg_replace по коду шаблона, переопределив класс нужного контроллера. Оба способа не очень-то привлекательно выглядят. Кир сказал, что у него есть некоторые мысли по работе дополнений с шаблонами, но он не уверен, что успеет их реализовать в 1.0. Впрочем, это настолько важно, что я думаю, эту доработку можно ожидать в ближайшие месяца три-четыре.

Еще один недостаток – отсутствие возможности расширять некоторые функции системы без редактирования исходников. В глаза сейчас бросается как минимум два таких момента: невозможность изменить поисковый движок (например, на Sphinx) и невозможность встроить иные платежные системы для премиум-подписок вместо PayPal, который в России крайне непопулярен..

Не существует стандартного механизма добавления новых BB-кодов в систему, как это сделано во всех форумных движках. Добавление BB-кодов возможно через дополнения, а удобный редактор реализован только для добавления BB-кодов медиаконтента вроде YouTube.

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

Разработчики ждали автоустановку дополнений прямо из архивов с автоматической распаковкой файлов и импортом файла настроек дополнения, но она пока не реализована, как и автоматическое обновление дополнений. Думаю, эти функции отложены на приличный срок. Авторам есть над чем пока потрудиться.

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

Еще раз напоминаю, что авторы полностью в курсе изложенных отрицательных моментов и, скорее всего, исправят ситуацию в самое ближайшее время. Все же вышла пока только Beta 1.

Общие впечатления

Вообще код XenForo произвел на меня приятное впечатление. Он красивый, понятный, гармоничный, полон комментариев и ООП. Сначала, посмотрев на количество классов, я собирался испугаться и отложить статью до лучших времен, но теперь, подбираясь к концу, я могу сказать, что уже почти все ок, я немного въехал, как тут все устроено. Надеюсь, что и вы немножко тоже.

Конечно, при внимательном взгляде заметны некоторые шероховатости, но в целом архитектура система позволяет их ликвидировать с минимальными трудозатратами.

Кстати, я очень ждал выхода PHPBB3, хотел им заняться серьезно. Но его архитектура для меня выглядит гораздо менее четкой и логичной, чем архитектура XenForo. Честно признаться, я так и не въехал в Olympus. Будем ждать четверку на Symfony2

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

Дополнительные материалы

К сожалению, объем журнальной статьи ограничен, а еще так много хочется рассказать. Если разработка под XenForo Framework вас заинтересовала, отсылаю вас к разделу разработчиков на форуме Российского сообщества XenForo. Там будут публиковаться все дополнительные материалы, примеры и прочее. Если при прочтении этой статьи у вас возникли вопросы, вы можете задать их там же в соседнем разделе.

Я буду благодарен любым комментариям по поводу этой статьи. Присылайте ваши мнения и пожелания на email.

Метки: , , ,

Ответить

Для отправки комментария вам нужно зарегистрироваться. Войти.