Пользователь
0,0
рейтинг
1 ноября 2012 в 20:52

Разработка → Связка MODX Revolution и форума phpBB

MODX*, CMS*
Обновлено 6 Ноября 2012 года.
В предыдущей версии было сделано не очень хорошо и повылазили камни из под воды.
Обновлено 7 Ноября 2012 года.
Исправлена мелкая ошибка
Обновлено 13 Ноября 2012 года.
Исправлен только файл /forum/includes/auth/auth_modx.php:

Версия phpBB: 3.0.11
Версия MODX: 2.2.5-pl

Папка сайта: /
Папка форума: /forum

Базы данных у меня разные, но можно и одну использовать, вроде все должно быть путем.

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


Плагин авторизации phpBB


Для авторизации на форуме используется система «плагинов авторизации», вкратце об них.

Чтобы использовать плагин авторизации, надо:

1. Придумать имя плагину авторизации, например: modx
2. Создать файл /forum/includes/auth/auth_modx.php (суффикс имени файла (modx) == имя плагина)
3. В файле /forum/includes/auth/auth_modx.php, должна быть минимум одна функция login_modx (суффикс == имя плагина)
4. Отключить регистрацию на форуме: ОБЩИЕ -> Регистрация пользователей -> Отключить регистрацию
5. В админ панели форума: ОБЩИЕ -> Аутентификация -> выбрать из списка Modx

Код файла /forum/includes/auth/auth_modx.php:
<?php

# /forum/includes/auth/auth_modx.php

if (!defined('IN_PHPBB')){
    exit;
}

/**
 * возвращает информацию о текущем пользователе
 */
function get_user_data(){

    // Подключаем
    define('MODX_API_MODE', true);
    require dirname(dirname(dirname(dirname(__FILE__)))) . '/index.php'; // у меня форум лежит в /forum

    // MODX переназначает на свой обработкчик ошибок, и сообщения форума выводятся криво,
    // поэтому надо обратно назначить обработчик ошибок на форумный:
    set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');

    // берем пользователя
    if($modx->user->get('id') != 0){ // Если не anonimous
        $result['username'] = $modx->user->get('username');
        $profile = $modx->user->getOne('Profile');
        $result['user_email'] = $profile->get('email');
        $fields = $profile->get('extended');
        $result['user_from'] = (string) $fields['region']; // Если поле пустое, то возвращает NULL, а в БД форума не может быть NULL
        // Сюда можно добавить другие поля профиля, например:
        // $result['имя_столбца_в_БД_форума_в_таблице_users'] = Значение_поля_из_БД_modx;
        // Все поля перечисленные здесь проверяются, и если изменились в MODX, меняются и на форуме,
        // например: Поменялся у пользователя в MODX extended поле region, автоматически меняется в БД форума поле user_from
        // автообновление происходит в функции validate_session_modx (ниже)
    }

    return $result;
}

/**
 * Функция, отвечающая за авторизацию.
 */
function login_modx(){

    $auth = get_user_data();

    // если авторизация невозможна
    if (!is_array($auth) || empty($auth))
    {
        return array(
            'status' => LOGIN_ERROR_USERNAME,
            'error_msg' => 'ACCESS_DIRECTLY_DENIDED',
            'user_row' => array('user_id' => ANONYMOUS),
        );
    }

    global $db;
    $sql = 'SELECT user_id, username, user_password, user_email, user_from, user_type
           FROM ' . USERS_TABLE . "
           WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($auth['username'])) . "'";
    $result = $db->sql_query($sql);
    $row = $db->sql_fetchrow($result);
    $db->sql_freeresult($result);

    if ($row){

        foreach($auth as $auK => $auV){
            if($row[$auK] != $auV){ // Если поле пользователя форма не равно полю из modx (хоть одно)
                // Сделать UPDATE
                unset($auth['username']);
                $sql = "UPDATE " . USERS_TABLE . " SET " . $db->sql_build_array('UPDATE', $auth) .
                    " WHERE user_id = '" . $db->sql_escape($row['user_id']) . "'";
                $db->sql_query($sql);
                break;
            }
        }

        $res = array(
            'status'     => LOGIN_SUCCESS,
            'error_msg'  => false,
            'user_row'     => array(
                'user_id' => $row['user_id'],
                'username'       => $row['username'],  // Отображаемое имя пользователя
                'user_email'     => $row['user_email'],  // E-mail пользователя, если существует
                'user_from'     => $row['user_from'],
                'user_type'      => 0,
                'group_id' => 2
            )
        );
        return $res;
    }

    // Сообщаем, что авторизация прошла успешно.
    $res = array(
        'status'     => LOGIN_SUCCESS_CREATE_PROFILE,
        'error_msg'  => false,
        'user_row'     => array(
            "username"       => $auth['username'],  // Отображаемое имя пользователя
            "user_email"     => $auth['user_email'],  // E-mail пользователя, если существует
            "user_from"     => $auth['user_from'],
            "user_type"      => 0,
            "group_id" => 2
        ),
    );
    return $res;

}

/**
 * Функция, отвечающая за регистрацию и авторизацию пользователя при первом посещении.
 */
function autologin_modx(){
    $user_row = login_modx();
    // если пользователь еще не зарегистрирован
    if ($user_row['status'] == LOGIN_SUCCESS_CREATE_PROFILE)
    {
        global $phpbb_root_path, $phpEx;
        if (!function_exists('user_add'))
        {
            include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
        }
        $user_row['user_row']['user_id'] = user_add($user_row['user_row']);
    }
    // возвращаем данные пользователя
    global $db;
    $sql = 'SELECT * FROM ' . USERS_TABLE . " WHERE user_id = '" . $db->sql_escape($user_row['user_row']['user_id']) . "'";
    $result = $db->sql_query($sql);
    $row = $db->sql_fetchrow($result);
    $db->sql_freeresult($result);
    return $row;
}

function logout_modx(){
    // Подключение modx API
    define('MODX_API_MODE', true);
    require dirname(dirname(dirname(dirname(__FILE__)))) . '/index.php';
    $modx->getService('error','error.modError');
    $modx->runProcessor('/security/logout');
    //$modx->cacheManager->refresh();
}

function validate_session_modx($locUser){
    $auth = get_user_data();

    if($locUser['username'] == 'Anonymous'){
        if($auth){
            return false;
        }else{
            return true;
        }
    }else{
        // Взять пользователя modx, и если он пуст, то выйти на форуме
        if(!$auth){
            // Выйти из форума
            global $user;
            $user->session_kill();
            $user->session_begin();
        }elseif(($auth['username'] != $locUser['username'])){
            return false;
        }
        return true;
    }
}
?>


Админ форума


Так как авторизация почти полностью происходит на стороне MODX, то админ форума (имя пользователя, например admin), должен быть зарегистрирован в MODX.

Теперь, допустим, у нас есть пользователь admin в MODX, и у форума админ с тем же именем admin.
Проблема в том, что администратор форума должен подтвердить свой пароль, который не может свериться, т.к. авторизация у нас в MODX, а не через БД форума.

image

Поэтому отключаем дополнительную сверку пароля админа форума:
В файле: /forum/adm/index.php
// Have they authenticated (again) as an admin for this session?
if (!isset($user->data['session_admin']) || !$user->data['session_admin'])
{
	login_box('', $user->lang['LOGIN_ADMIN_CONFIRM'], $user->lang['LOGIN_ADMIN_SUCCESS'], true, false);
}

Меняем на:
// Have they authenticated (again) as an admin for this session?
//if (!isset($user->data['session_admin']) || !$user->data['session_admin'])
//{
//	login_box('', $user->lang['LOGIN_ADMIN_CONFIRM'], $user->lang['LOGIN_ADMIN_SUCCESS'], true, false);
//}

После:
if (!$auth->acl_get('a_'))
{
	trigger_error('NO_ADMIN');
}

Добавить строку:
$user->data['session_admin'] = 1;

Вход, восстановление пароля


В файле /forum/ucp.php, залогиниться одновременно на сайте и форуме, через форму авторизации на форуме:
Между case 'login': и break; (включительно):
    case 'login':
        define('MODX_API_MODE', true);
        require dirname(dirname(__FILE__)) . '/index.php';
        $modx->getService('error','error.modError');
        set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');

        if($_REQUEST["username"] and $_REQUEST["password"]){
            $data = array(
                'username' => $_REQUEST["username"],
                'password' => $_REQUEST["password"],
                'rememberme' => 1,
                'login_context' => 'web',
            );
            $response = $modx->runProcessor('/security/login', $data);
            if ($response->isError()) {
                trigger_error($response->getMessage());
            }
        }

        if ($user->data['is_registered'])
        {
            redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
        }

        login_box(request_var('redirect', "index.$phpEx"));
        break;

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

Чтобы по ссылке «Забыли пароль?» на форуме, попадали на страницу восстановления пароля MODX (/forum/ucp.php):

    case 'sendpassword':
        define('MODX_API_MODE', true);
        require dirname(dirname(__FILE__)) . '/index.php';
        $modx->getService('error','error.modError');
        set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
        $modx->sendRedirect($modx->makeUrl(865,'','','full')); // где 865 - это ID ресурса MODX с формой сброса пароля
        break;

Статья, которая была взята за основу:
Интеграция пользователей сайта и форума на phpbb 3
@Petja
карма
9,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (6)

  • +1
    Спасибо, полезно. Особенно ввиду отсутствия рабочего решения форума в репозитории modx.com
  • 0
    Спасибо.
    Попробую перейти по Вашему примеру со связки Evo+phpBB
  • 0
    Немного не по теме, но может кто-то не знает.
    Сейчас идёт тестирование нового дизайна форума Discuss (ссылку Райан Трэш просил не публиковать). Новый дизайн выглядит очень приятно. Возможно скоро компонент будет доступен для скачивания.
    • 0
      Спасибо за инфу! Но на данный момент Discuss в бета версии и использовать его на паблике не рекомендуют.
    • 0
      К тому же с phpBB работает много народа, постоянно выходят обновления, есть серьезная русскоязычная поддержка в виде форума phpbbguru.
      И он, по сравнению с MODX (имхо), достаточно прост в понимании.
      • 0
        Я согласен, Discuss даже если скоро выйдет, долго с ним нужно будет ещё разбираться и возможно переводить на русский.
        Ваш подход к интеграции мне понравился.

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