function IndexForumMarkRead()
{
    $mark_forums = array();
    // Форумы на которых устанавливать метки
    $forums_tree = ForumTree::Instance();
    if (isset($_GET['forum'])) {
        // Только внутри определённого форума
        $forum = SafeDB($_GET['forum'], 11, int);
        $mark_forums = $forums_tree->GetAllAccessForumId($forum);
    } else {
        // На всех форумах
        $mark_forums = $forums_tree->GetAllAccessForumId();
    }
    $user_id = System::user()->Get('u_id');
    if (System::user()->Auth) {
        // Загружаем данные о прочтении тем пользователем
        $read_data = Forum_Marker_GetReadData();
        // Загружаем топики (агрегированы по forum_id)
        $topics = ForumCacheGetTopics();
        $del_where = '';
        $insert_values = array();
        $time = time();
        foreach ($mark_forums as $forum_id) {
            if (!isset($topics[$forum_id])) {
                continue;
            }
            foreach ($topics[$forum_id] as $topic) {
                $tid = SafeEnv($topic['id'], 11, int);
                // Не прочитана или метка устарела
                if (!isset($read_data[$topic['id']])) {
                    $insert_values[] = "'{$user_id}','{$tid}','{$time}'";
                    // Добавить новую метку
                } elseif ($read_data[$topic['id']]['date'] < $topic['last_post']) {
                    $del_where .= "(`tid`='{$tid}' and `mid`= '{$user_id}') or ";
                    // Удалить текущую метку
                    $insert_values[] = "'{$user_id}','{$tid}','{$time}'";
                    // Добавить новую метку
                }
            }
        }
        // Удаляем устаревшие метки
        if ($del_where != '') {
            $del_where = substr($del_where, 0, -4);
            // Удаляем .or.
            System::database()->Delete('forum_topics_read', $del_where);
        }
        // Добавляем новые метки
        // TODO: В будущем нужно перейти на InnoDB и использовать транзакции как в MySQL так и в FilesDB.
        if (count($insert_values) > 0) {
            foreach ($insert_values as $vals) {
                System::database()->Insert('forum_topics_read', $vals);
            }
        }
    }
    GO(GetSiteUrl() . Ufu('index.php?name=forum' . (isset($forum) ? '&op=showforum&forum=' . $forum : ''), 'forum/' . (isset($forum) ? '{forum}/' : '')));
}
function IndexForumSubscription()
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Проверки на доступ
    if (CheckGet('topic')) {
        // Тема
        $topic_id = SafeEnv($_GET['topic'], 11, int);
        System::database()->Select('forum_topics', "`id`='{$topic_id}'");
        if (System::database()->NumRows() > 0) {
            $topic = System::database()->FetchRow();
        } else {
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_access_category']);
            return;
        }
        if ($topic['delete'] == '1') {
            // Тема на удалении
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['topic_basket'] . '.' . $forum_lang['no_topic_basket_edit']);
            return;
        }
        if ($topic['close_topics'] == '1') {
            // Тема закрыта
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['topic_close_for_discussion'] . '.' . $forum_lang['no_create_new_message_current_topic_add']);
            return;
        }
        // Форум
        $forum_id = SafeEnv($topic['forum_id'], 11, int);
        if (!isset($forums_tree->IdCats[$forum_id])) {
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
            return;
        }
        $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
        if (!$forum_config['access']) {
            // Доступ
            System::site()->AddTextBox($forum_lang['error'], $forum_config['access_reason']);
            return;
        } elseif (!$forum_config['new_message_email']) {
            // Разрешено ли подписываться на новые сообщения (+ защита от гостей)
            System::site()->AddTextBox($forum_lang['error'], $forum_config['add_post_reason']);
            return;
        }
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
        return;
    }
    Forum_Subscription($topic_id);
    // Подписка (обратное действие, если пользователь уже подписан)
    GO(Ufu('index.php?name=forum&op=showtopic&topic=' . $topic_id . '&view=lastpost', 'forum/topic{topic}-new.html'));
}
function IndexForumAddPost()
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Проверки на доступ
    if (CheckGet('topic')) {
        // Тема
        $topic_id = SafeEnv($_GET['topic'], 11, int);
        System::database()->Select('forum_topics', "`id`='{$topic_id}'");
        if (System::database()->NumRows() > 0) {
            $topic = System::database()->FetchRow();
        } else {
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_access_category']);
            return;
        }
        if ($topic['delete'] == '1') {
            // Тема на удалении
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['topic_basket'] . '.' . $forum_lang['no_topic_basket_edit']);
            return;
        }
        if ($topic['close_topics'] == '1') {
            // Тема закрыта
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['topic_close_for_discussion'] . '.' . $forum_lang['no_create_new_message_current_topic_add']);
            return;
        }
        // Форум
        $forum_id = SafeEnv($topic['forum_id'], 11, int);
        if (!isset($forums_tree->IdCats[$forum_id])) {
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
            return;
        }
        $forum = $forums_tree->IdCats[$forum_id];
        $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
        if (!$forum_config['access']) {
            // Доступ
            System::site()->AddTextBox($forum_lang['error'], $forum_config['access_reason']);
            return;
        } elseif (!$forum_config['add_post']) {
            // Разрешено ли добавлять новые сообщения (+ защита от гостей)
            System::site()->AddTextBox($forum_lang['error'], $forum_config['add_post_reason']);
            return;
        }
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
        return;
    }
    // Добавляем сообщение
    if (!CheckPost('text') || strlen($_POST['text']) == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
        return;
    }
    $name = System::user()->Get('u_name');
    $email = System::user()->Get('u_email');
    $hideemail = System::user()->Get('u_hideemail');
    $site = System::user()->Get('u_homepage');
    $icq = System::user()->Get('u_icq');
    $uid = System::user()->Get('u_id');
    $text = SafeEnv($_POST['text'], 0, str);
    $vals = Values('', $topic_id, $uid, time(), $name, $site, $email, $hideemail, $icq, $text, getip(), 0);
    System::database()->Insert('forum_posts', $vals);
    // Обновляем время прочтения темы автором сообщения
    $user_id = System::user()->Get('u_id');
    System::database()->Delete('forum_topics_read', "`tid`='{$topic_id}' and `mid`='{$user_id}'");
    $time = time();
    $vals = "'{$user_id}','{$topic_id}','{$time}'";
    System::database()->Insert('forum_topics_read', $vals);
    // Информация о последнем сообщении в теме и форуме
    $forum['posts'] = (int) $forum['posts'] + 1;
    $topic['posts'] = (int) $topic['posts'] + 1;
    IndexForumSetLastPostInfo($forum, $topic);
    // Добавляем очков пользователю
    System::user()->ChargePoints(System::config('points/forum_post'));
    // Увеличиваем счётчик сообщений пользователя
    ForumCalcUserCounters(1);
    // Делаем рассылку подписчикам на эту тему
    Forum_Subscription_Send($topic_id);
    // Очищаем кэш форума
    ForumCacheClear();
    GO(Ufu('index.php?name=forum&op=showtopic&topic=' . $topic_id . '&view=lastpost#last', 'forum/topic{topic}-new.html'));
}
function IndexForumUserTopics()
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Проверка данных
    if (isset($_GET['user'])) {
        $user_id = SafeEnv($_GET['user'], 11, int);
        $user = GetUserInfo($user_id);
        if ($user === false) {
            // Пользователь не найден
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_user']);
            return;
        }
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_data']);
        // Нет параметра
        return;
    }
    // Параметры постраничной навигации
    if (isset($_GET['page'])) {
        $page = SafeEnv($_GET['page'], 11, int);
    } else {
        $page = 1;
    }
    $topics_on_page = System::config('forum/topics_on_page');
    // Устанавливаем заголовок страницы
    $function_title = $forum_lang['allusertopics'] . ' "' . $user['name'] . '"';
    System::site()->SetTitle(SafeDB($function_title, 255, str) . ' - ' . ($page > 1 ? $forum_lang['page'] . $page . ' - ' : '') . $forum_lang['forum']);
    $forum_nav_url = Ufu('index.php?name=forum&op=usertopics&user='******'forum/usertopics/{user}-{page}/', true);
    //$forum_url = Ufu('index.php?name=forum&op=usertopics&user='******'forum/usertopics/{user}/');
    // Объекты статистики и онлайн
    $statistics = ForumStatistics::Instance();
    $online = ForumOnline::Instance('0', '0', true);
    // Обновляем статус онлайн
    // Инициализируем статистику
    $statistics->Initialize($forum_lang['statistics_cat']);
    // Хлебные крошки
    System::site()->BreadCrumbAdd($function_title);
    $auth = System::user()->Auth;
    $is_admin = System::user()->isAdmin();
    $current_user_id = System::user()->Get('u_id');
    // Загружаем данные корзины для видимых топиков
    $basket = ForumBasketGetData('forum_basket_topics');
    // Загружаем информацию по топикам в $topics_data и считаем статистику (кэшировать статистику)
    $topics_data = ForumCacheGetTopics();
    // Запрашиваем данные тем (агрегированы по форумам)
    $topics = array();
    // Сюда будем добавлять топики для вывода
    $resolve_cats = $forums_tree->GetAllAccessForumId(0);
    // Считаем только в открытых для доступа форумах
    foreach ($resolve_cats as $resolve_cat) {
        if (!isset($topics_data[$resolve_cat])) {
            continue;
        }
        foreach ($topics_data[$resolve_cat] as $topic) {
            // Отсеиваем
            if ($topic['starter_id'] == $user_id) {
                // Добавляем данные из корзины, если топик удалён в корзину
                $topic['status'] = '';
                $topic['show_delete'] = $is_admin;
                if ($topic['delete'] && isset($basket[$topic['id']]) && $auth && ($is_admin || $topic['starter_id'] == $current_user_id)) {
                    // Добавляем сообщение - "Удалено в корзину"
                    $topic['status'] = ForumBasketRender($topic['id'], $topic['title'], $basket, false);
                    $topic['show_delete'] = false;
                } elseif ($topic['delete']) {
                    continue;
                    // Удалён топик и корзина не показывается для этого пользователя
                }
                $statistics->hits += $topic['hits'];
                $statistics->AddTopicAuthor($topic['starter_id'], $topic['starter_name']);
                $statistics->topics_count += 1;
                $statistics->reply_count += $topic['posts'];
                $topics[] = $topic;
            }
        }
    }
    unset($topics_data);
    // Заголовки (Темы, Ответов, Просмотры)
    System::site()->AddBlock('statistik', true, false, 'stat');
    System::site()->SetVars('statistik', array('count_read' => ''));
    // Отключаем некоторые блоки
    System::site()->AddBlock('topic_form', false, false, 'form');
    System::site()->AddBlock('topic_right', false, false, 'topic');
    System::site()->AddBlock('forum', false);
    System::site()->AddBlock('forum_guest_message', false);
    // Блоки шаблона
    // Ссылки, Отметить все как прочитанные и показать все не прочитанные темы.
    $vars_is_forum_member = array();
    $vars_is_forum_member['url'] = '<a href="' . Ufu('index.php?name=forum&op=markread', 'forum/markread/') . '">' . $forum_lang['mark_all_read'] . '</a>';
    $vars_is_forum_member['viewnoreadurl'] = '<a href="' . Ufu('index.php?name=forum&op=viewnoread', 'forum/viewnoread/') . '">' . $forum_lang['viewnoread'] . '</a>';
    $vars_is_forum_member['forum_id'] = '0';
    if (!System::site()->HasBlock('is_forum_member')) {
        System::site()->AddBlock('is_forum_member', AccessIsResolved(2), false, 'mark');
    }
    System::site()->SetVars('is_forum_member', $vars_is_forum_member);
    // Последние темы форума
    System::site()->AddBlock('old', true, false, 'mark');
    $vars_old = array();
    $vars_old['lasttopics'] = '<a href="' . Ufu('index.php?name=forum&op=lasttopics', 'forum/lasttopics/') . '">' . $forum_lang['lasttopics'] . '</a>';
    System::site()->SetVars('old', $vars_old);
    // Блок списка топиков
    System::site()->AddBlock('topics', true, true, 'topic');
    // Инициализируем постраничную навигацию
    $navigation = new Navigation($page);
    $navigation->FrendlyUrl = System::config('general/ufu');
    // Выводим топики в шаблон
    if (count($topics) == 0) {
        // В этом форуме пока нет ни одной темы
        System::site()->AddBlock('no_topics', true);
        $navigation->DisableNavigation();
    } else {
        // Вывод постраничной навигации
        $navigation->GenNavigationMenu($topics, $topics_on_page, $forum_nav_url);
        // Загружаем данные о прочтении тем
        $read_data = Forum_Marker_GetReadData();
        $visable_topics = false;
        // Вывод тем из этой категории с постраничной навигацией
        foreach ($topics as $topic) {
            $forum_config = $forums_tree->GetForumConfigRecursive($topic['forum_id']);
            // Конфигурация просматриваемого форума
            // Статус прочитано
            $read = true;
            // прочитано
            if ($auth && (!isset($read_data[$topic['id']]) || $topic['last_post'] > $read_data[$topic['id']]['date'])) {
                $read = false;
            }
            $topic = ForumTopicFilterData($topic);
            // Фильтрация данных топика
            $topic['on'] = !$read;
            $topic['off'] = $read;
            if (!$topic['close']) {
                $topic['close'] = $forum_config['close'];
                $topic['begin'] = !$forum_config['close'];
            }
            $topic['page'] = $page;
            $visable_topics = true;
            System::site()->AddSubBlock('topics', true, $topic);
        }
        System::site()->AddBlock('no_topics', !$visable_topics);
    }
    // Блоки модерации
    ModerationForumTopicsBlocks();
    // Подключаем шаблон
    System::site()->AddTemplatedBox('', 'module/forum_topics.html');
    // Выводм блок онлайн
    $online->Render('0', '0', $forum_lang['all_online'], 'forum_topics_online');
    // Выводим статистику
    $statistics->Render('forum_topics_statistics');
    // Выбор периода и быстрый переход
    ForumQuickTransitionBox(0, $forum_lang['quick_transition']);
}
/**
 * Главная страница форума, список форумов в категории или подфорумов в форуме.
 * @param int   $cat_id Идентификатор просматриваемого каталога
 * @global type $forum_lang
 * @return type
 */
function IndexForumMain($cat_id = null, &$topics_data = null)
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    if (isset($cat_id)) {
        $parent = $forums_tree->IdCats[$cat_id]['parent_id'];
        // Чтобы сделать просмотр категории нужно её выводить как подкатегорию родительской категории
        $cat = $parent == 0;
        // Просмотр категории или главной страницы форума
        $main = false;
        // Не главная страница (просмотр категории или форума)
    } else {
        $cat = true;
        // Однозначно просматриваем категрию или главную страницу форума (выводим блоки онлайн и статистики)
        $cat_id = 0;
        $parent = 0;
        // Корневой раздел в качестве родительской категории
        $main = true;
        // Главная страница
    }
    // Нет категорий, выводим сообщение
    if (!isset($forums_tree->Cats[$parent]) && $cat) {
        System::site()->AddTextBox($forum_lang['forum'], $forum_lang['no_category']);
        return;
    }
    if ($cat) {
        // Выводим категорию или главная страница форума (без топиков)
        // Устанавливаем заголовок страницы
        if (!$main) {
            System::site()->SetTitle(SafeDB($forums_tree->IdCats[$cat_id]['title'], 255, str) . ' - ' . $forum_lang['forum']);
        }
        // Объекты статистини и онлайн
        $statistics = ForumStatistics::Instance();
        $online = ForumOnline::Instance($cat_id, '0', true);
        // Инициализируем статистику
        $statistics->Initialize($forum_lang['statistics']);
        // Загружаем информацию по топикам в $topics_data и считаем статистику (кэшировать статистику)
        $topics_data = ForumCacheGetTopics();
        // Запрашиваем данные тем (агрегированы по форумам)
        $resolve_cats = array_keys($topics_data);
        foreach ($resolve_cats as $resolve_cat) {
            if (!isset($topics_data[$resolve_cat])) {
                continue;
            }
            foreach ($topics_data[$resolve_cat] as $topic) {
                $statistics->hits += $topic['hits'];
                $statistics->AddTopicAuthor($topic['starter_id'], $topic['starter_name']);
            }
        }
        // Подсчитываем количество тем и постов
        $counters = $forums_tree->GetCountersRecursive($cat_id);
        $statistics->topics_count = $counters['files'];
        $statistics->reply_count = $counters['cats'];
        // Выводим хлебные крошки
        $forums_tree->BreadCrumbsF($cat_id);
        System::site()->BreadCrumbsLastUrl = true;
        // Ссылки, Отметить все как прочитанные и показать все не прочитанные темы.
        System::site()->AddBlock('is_forum_member', AccessIsResolved(2), false, 'mark');
        $vars_is_forum_member = array();
        $vars_is_forum_member['url'] = '<a href="' . Ufu('index.php?name=forum&op=markread', 'forum/markread/') . '">' . $forum_lang['mark_all_read'] . '</a>';
        $vars_is_forum_member['viewnoreadurl'] = '<a href="' . Ufu('index.php?name=forum&op=viewnoread', 'forum/viewnoread/') . '">' . $forum_lang['viewnoread'] . '</a>';
        System::site()->Blocks['is_forum_member']['vars'] = $vars_is_forum_member;
        // Последние темы форума
        System::site()->AddBlock('old', true, false, 'mark');
        $vars_old = array();
        $vars_old['lasttopics'] = '<a href="' . Ufu('index.php?name=forum&op=lasttopics', 'forum/lasttopics/') . '">' . $forum_lang['lasttopics'] . '</a>';
        System::site()->Blocks['old']['vars'] = $vars_old;
    }
    // Загружаем данные о прочтении тем
    $read_data = Forum_Marker_GetReadData();
    $auth = System::user()->Auth;
    // Блоки форума
    System::site()->AddBlock('forums', true, true, 'forum');
    System::site()->AddBlock('is_no_sub_forum', $cat, false);
    // Блок со статистикой и онлайн (отключается в категории)
    $visable_cats = false;
    // Выведена хотябы одна категория с форумом - если нет то показываем ошибку
    foreach ($forums_tree->Cats[$parent] as $category) {
        // Категории
        if (!$main && ($category['id'] != $cat_id || !isset($forums_tree->Cats[$category['id']]))) {
            // Если просматриваем только одну категорию
            continue;
        }
        // Рекурсивно определяем настройки
        $forum_config = $forums_tree->GetForumConfigRecursive($category['id']);
        // Нет доступа или форум не виден или отключён
        if (!$forum_config['access']) {
            continue;
        }
        $visable_cats = true;
        $category = IndexForumDataFilter($category, $forum_config);
        // Выводим категорию
        IndexForumCatOpen($category);
        IndexForumRender($category);
        // Выводим форумы
        foreach ($forums_tree->Cats[$category['id']] as $forum) {
            $forum_id = $forum['id'];
            $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
            // Нет доступа или форум не виден или отключён
            if (!$forum_config['access']) {
                continue;
            }
            $forum = IndexForumDataFilter($forum, $forum_config);
            // Обрабатываем подфорумы
            $subforums = array();
            if (isset($forums_tree->Cats[$forum_id])) {
                foreach ($forums_tree->Cats[$forum_id] as $sforum) {
                    // Подфорумы, нужно добавить только пометку о прочтении и обработать
                    $read = true;
                    // прочитан
                    if ($auth) {
                        $childs_forums = $forums_tree->GetAllChildId($sforum['id']);
                        foreach ($childs_forums as $child_forum_id) {
                            if (!isset($topics_data[$child_forum_id])) {
                                continue;
                            }
                            foreach ($topics_data[$child_forum_id] as $topic) {
                                if (!isset($read_data[$topic['id']]) || $topic['last_post'] > $read_data[$topic['id']]['date']) {
                                    $read = false;
                                    // не прочитан
                                    break;
                                }
                            }
                            if (!$read) {
                                break;
                            }
                        }
                    }
                    $sforum = IndexForumDataFilter($sforum);
                    $sforum['read'] = $read;
                    $subforums[] = $sforum;
                }
            }
            // Определяем статус "прочинано" для форума
            $read = true;
            // прочитан
            if ($auth) {
                $childs_forums = $forums_tree->GetAllChildId($forum_id);
                foreach ($childs_forums as $child_forum_id) {
                    if (!isset($topics_data[$child_forum_id])) {
                        continue;
                    }
                    foreach ($topics_data[$child_forum_id] as $topic) {
                        if (!isset($read_data[$topic['id']]) || $topic['last_post'] > $read_data[$topic['id']]['date']) {
                            $read = false;
                            // не прочитан
                            break;
                        }
                    }
                    if (!$read) {
                        break;
                    }
                }
            }
            // Вывод форума в шаблон
            IndexForumRender($forum, false, $read, $subforums);
        }
        // Закрываем категорию
        IndexForumCatClose($category);
    }
    if ($visable_cats) {
        // Шаблон форума (полезно подключать шаблоны вконце, там может быть PHP код)
        System::site()->AddTemplatedBox('', 'module/forums.html');
    }
    if ($cat) {
        // Не при просмотре форума (субфорумы + топики)
        if (!$visable_cats) {
            System::site()->AddTextBox($forum_lang['forum'], $forum_lang['no_category']);
            return;
        }
        // Выводим блок онлайн
        $online->Render($cat_id, '0', $cat_id == 0 ? $forum_lang['all_online'] : $forum_lang['current_category']);
        // Выводим статистику
        $statistics->Render();
        // Быстрый переход
        if (!$cat) {
            ForumQuickTransitionBox($cat_id, $forum_lang['quick_transition']);
        }
    }
}
 /**
  * Возвращает синглтон
  * @param null $Forums
  * @return ForumTree
  */
 public static function Instance($Forums = null)
 {
     if (!self::$_instance instanceof ForumTree) {
         if (!isset($Forums)) {
             $Forums = ForumCacheGetForums();
             // Возвращает таблицу форумов (категорий)
         }
         self::$_instance = new ForumTree($Forums, 'id', 'parent_id', 'title', 'topics', 'posts');
         self::$_instance->moduleName = 'forum';
         self::$_instance->TopCatName = 'Форум';
     }
     return self::$_instance;
 }
 public function GetCatOnlineCount($cat)
 {
     $count = 0;
     $forum_tree = ForumTree::Instance();
     // Пользователи просматривающие каталог включая все дочерние каталоги и темы
     $all_cats = $forum_tree->GetAllChildId($cat);
     foreach ($all_cats as $cat_id) {
         // Просматривают каталог
         if (isset($this->online_cat[$cat_id])) {
             $count += $this->online_cat[$cat_id]['c'];
         }
         // Просматривают темы
         if (isset($this->cat_topics_id[$cat_id])) {
             foreach ($this->cat_topics_id[$cat_id] as $topic_id) {
                 $count += $this->online_topic[$topic_id]['c'];
             }
         }
     }
     return $count;
 }
function IndexForumShowTopic($one_post = false)
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Вспомогательные переменные
    $user_auth = System::user()->Auth;
    $user_id = System::user()->Get('u_id');
    $user_admin = System::user()->isAdmin();
    $time = time();
    $max_word_length = System::config('forum/max_word_length');
    if (isset($_GET['topic'])) {
        $topic_id = SafeEnv($_GET['topic'], 11, int);
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_topic']);
        return;
    }
    // Берём тему и проверяем на доступ
    System::database()->Select('forum_topics', "`id`='" . $topic_id . "'");
    if (System::database()->NumRows() == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_topic']);
        return;
    }
    $topic = System::database()->FetchRow();
    if (!$user_admin && $topic['starter_id'] == $user_id && $topic['delete'] == '1') {
        // Тема удалена в корзину (только админы видят корзину и автор темы)
        System::site()->AddTextBox($forum_lang['topic_basket_current_post'], '<p align="center">' . $forum_lang['topic_basket_post'] . '.<br><input type="button" value="' . $forum_lang['back'] . '"onclick="history.back();"></p>');
        return;
    }
    // Проверяем доступ к форуму
    $forum_id = SafeEnv($topic['forum_id'], 11, int);
    $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
    // Параметры доступа на форум
    if (!$forum_config['access']) {
        System::site()->AddTextBox($forum_lang['error'], $forum_config['access_reason']);
        // Нет доступа в этот форум
        return;
    }
    // $forum_config['add_post'] - право добавлять сообщения
    // $forum_config['add_post_reason'] - причина запрета добавления сообщений
    // $forum_config['no_link_guest'] - скрывать ссылки от гостей
    // $forum_config['new_message_email'] - разрешить подписку на новые сообщения
    // Определяем следующую и предыдущую темы
    $topics_data = ForumCacheGetTopics();
    $topics_data = $topics_data[$forum_id];
    $prev_topic = null;
    $next_topic = null;
    $find = false;
    foreach ($topics_data as $topic_row) {
        if ($topic_row['id'] == $topic_id) {
            $find = true;
            continue;
        }
        if ($find) {
            $next_topic = $topic_row;
            break;
        }
        $prev_topic = $topic_row;
    }
    // Параметры постраничной навигации
    if (isset($_GET['page'])) {
        $page = SafeEnv($_GET['page'], 11, int);
    } else {
        $page = 1;
    }
    if (isset($_GET['view']) && $_GET['view'] == 'lastpost') {
        $lastpost = true;
    } else {
        $lastpost = false;
    }
    $posts_on_page = System::config('forum/posts_on_page');
    // Обновляем метку о прочтении темы, если пользователь авторизован
    if ($user_auth) {
        System::database()->Delete('forum_topics_read', "`tid`='{$topic_id}' and `mid`='{$user_id}'");
        System::database()->Insert('forum_topics_read', "'{$user_id}','{$topic_id}','{$time}'");
    }
    // Объект онлайн
    $online = ForumOnline::Instance($forum_id, $topic_id);
    // Устанавливаем заголовок страницы
    $topic_title = SafeDB($topic['title'], 255, str);
    System::site()->SetTitle($topic_title . ($page > 1 ? ' - Страница ' . $page : ''));
    // Хлебные крошки
    $forums_tree->BreadCrumbsF($forum_id);
    System::site()->BreadCrumbAdd(SafeDB($topic['title'], 255, str));
    // Добавляем корзину (если тема удалена в корзину)
    if ($topic['delete'] == '1') {
        $basket_topics = ForumBasketGetData('forum_basket_topics');
        if (isset($basket_topics[$topic['id']])) {
            System::site()->AddTextBox($forum_lang['topic_basket_red'], ForumBasketRender($topic['id'], $topic['title'], $basket_topics, true));
        }
    }
    // Увеличиваем счётчик просмотров
    System::database()->Update('forum_topics', "`hits`='" . (SafeDB($topic['hits'], 11, int) + 1) . "'", "`id`='" . $topic_id . "'");
    // Инициализируем постраничную навигацию
    $navigation = new Navigation($page);
    $navigation->FrendlyUrl = System::config('general/ufu');
    // Загружаем сообщения из базы данных
    $basket_where = '';
    // Администратор (подготавливаем запрос выборки т.к. нужно знать сколько всего сообщений для постр. навигации)
    if ($user_auth) {
        if (!$user_admin) {
            $basket_where = " and (`delete`='0' or `user_id`='{$user_id}')";
            // Пользователь
        }
    } else {
        $basket_where = " and `delete`='0'";
        // Гость
    }
    $posts = System::database()->Select('forum_posts', ($one_post !== false ? "`id`='{$one_post}'" : "`object`='{$topic_id}'") . $basket_where);
    SortArray($posts, 'public', false);
    //Сортируем по дате
    // Вывод постраничной навигации
    if (count($posts) > $posts_on_page) {
        if ($lastpost) {
            $page = ceil(count($posts) / $posts_on_page);
        }
        $navigation->GenNavigationMenu($posts, $posts_on_page, Ufu('index.php?name=forum&op=showtopic&topic=' . $topic_id, 'forum/topic' . $topic_id . '-{page}.html', true), $page);
    } else {
        $navigation->DisableNavigation();
    }
    // Загружаем корзину для сообщений
    $basket = ForumBasketGetData('forum_basket_post');
    // Блок с информацией о теме
    System::site()->AddBlock('topic', true, false);
    System::site()->SetVars('topic', ForumTopicFilterData($topic));
    // Блок шаблонизатора для вывода сообщений
    System::site()->AddBlock('forum_posts', true, true, 'post');
    $is_forum_member = AccessIsResolved(2);
    // Для определения первого и последнего сообщения
    $i = 1;
    // Выводим сообщения в шаблонизатор
    foreach ($posts as $post) {
        $post_user_id = SafeDB($post['user_id'], 11, int);
        if ($post_user_id == 0) {
            continue;
        }
        $vars = array();
        // Обрабатываем текст сообщения
        if ($post['delete'] == '1') {
            // Сообщение удалено в корзину
            $vars['text'] = ForumBasketRender($post['id'], $post['message'], $basket);
        } else {
            $vars['text'] = HtmlChars($post['message']);
            if ($forum_config['no_link_guest']) {
                // Скрываем ссылки от гостей
                $replace = '<p class="notice">' . $forum_lang['hide_links_for_guests'] . '</p>';
                $vars['text'] = preg_replace('/\\<a[^\\>]*?(http|https|ftp|www)(.*?)\\<\\/a\\>/is', $replace, $vars['text']);
                $vars['text'] = preg_replace('/(http:\\/\\/|https:\\/\\/|ftp:\\/\\/|www\\.)?([a-zA-Z0-9]+)\\.(ru|su|com|org|net|info|name|ws|cc|tv|tel|kz|biz|mobi|asia|me|tw|ua)+([а-яА-Яa-zA-Z0-9\'~;,@#%&_\\!\\$\\^\\*\\(\\)\\-\\=\\+\\?\\.\\:\\/\\\\]*)?/is', $replace, $vars['text']);
            }
            SmiliesReplace($vars['text']);
            $vars['text'] = nl2br($vars['text']);
            $vars['text'] = BbCodePrepare($vars['text']);
            if ($max_word_length > 0) {
                $vars['text'] = word_wrapped_string($vars['text'], $max_word_length);
            }
        }
        // Обрабатываем данные сообщения
        // Пользователь
        $user_info = GetUserInfo($post_user_id);
        $vars['usertopics'] = '<a href="' . Ufu('index.php?name=forum&op=usertopics&user='******'forum/usertopics/{user}/') . '">' . $forum_lang['allusertopics'] . '</a>';
        if ($user_info['rank_name'] != '') {
            $vars['author'] = '<a href="' . Ufu('index.php?name=user&op=userinfo&user='******'user/{user}/info/') . '">' . $user_info['name'] . '</a>';
            $vars['author_name'] = $user_info['name'];
        } else {
            $vars['author'] = $post['name'];
            $vars['author_name'] = $post['name'];
        }
        if ($user_info['hideemail'] == '0') {
            $vars['email'] = AntispamEmail($user_info['email']);
        } else {
            $vars['email'] = '&nbsp;';
        }
        if ($user_info['url'] != '') {
            $vars['homepage'] = '<a href="http://' . $user_info['url'] . '" target="_blank">' . $user_info['url'] . '</a>';
        } else {
            $vars['homepage'] = '&nbsp;';
        }
        $vars['icq'] = $user_info['icq'];
        if ($user_info['online']) {
            $vars['status'] = $forum_lang['user_online'];
        } else {
            $vars['status'] = '';
        }
        $vars['rank_image'] = $user_info['rank_image'] != '' ? $user_info['rank_image'] : '';
        $vars['rank_name'] = $user_info['rank_name'] != '' ? $user_info['rank_name'] : '';
        $vars['avatar'] = $user_info['avatar_file'] != '' ? $user_info['avatar_file'] : GetPersonalAvatar(0);
        $vars['regdate'] = TimeRender($user_info['regdate'], false, true);
        if (isset($user_info['data']['forum_counters'])) {
            $vars['user_posts_count'] = $user_info['data']['forum_counters']['posts'];
            $vars['user_topics_count'] = $user_info['data']['forum_counters']['topics'];
        } else {
            $vars['user_posts_count'] = '0';
            $vars['user_topics_count'] = '0';
        }
        // Сообщение
        $vars['public'] = $forum_lang['added'] . TimeRender($post['public']);
        $vars['public_date'] = TimeRender($post['public']);
        $vars['ip'] = SafeDB($post['user_ip'], 19, str);
        $vars['topic_id'] = $topic_id;
        $vars['id'] = SafeDB($post['id'], 11, int);
        $vars['nodelete'] = SafeDB($post['delete'], 1, int) == 1 ? false : true;
        $vars['is_admin_and_nodelete'] = $vars['nodelete'] && $user_admin;
        $vars['page'] = $page;
        // is_current_user Пользователь является владельцем сообщения (кнопки редактировать и удалить)
        if ($post['delete'] == '0') {
            $vars['is_current_user'] = $user_id == $post['user_id'] && $topic['close_topics'] == '0' || $user_admin;
        } else {
            $vars['is_current_user'] = false;
        }
        if ($one_post === false) {
            $vars['num'] = $page > 1 ? $page * $posts_on_page - $posts_on_page + $i : $i;
            $vars['url'] = "javascript:link_post('" . GetSiteUrl() . Ufu("index.php?name=forum&op=post&topic=" . $topic_id . "&post=" . $post['id'], 'forum/t{topic}/post{post}.html') . "')";
        } else {
            $vars['num'] = '';
            $vars['url'] = 'javascript:history.go(-1)';
        }
        $vars['is_forum_member'] = $is_forum_member;
        System::site()->AddSubBlock('forum_posts', true, $vars, array(), 'module/forum_post.html');
        $i++;
    }
    // Форма добавления сообщений
    System::site()->AddBlock('post_form', $forum_config['add_post'], false);
    ForumRenderPostForm(false, $forum_id, $topic_id, 0, '', '', $is_forum_member);
    // Подписка на тему
    System::site()->AddBlock('subscription', $forum_config['new_message_email'], false, 'subs');
    $vars_subs = array();
    $vars_subs['topic'] = $topic_id;
    $vars_subs['sub_status'] = Forum_Subscription_Status($topic_id);
    $vars_subs['status'] = $vars_subs['sub_status'] ? 'Отписаться от этой темы' : 'Подписаться на эту тему';
    System::site()->SetVars('subscription', $vars_subs);
    System::site()->AddBlock('is_forum_member', $is_forum_member, false, 'marker');
    System::site()->SetVars('is_forum_member', array('id' => $topic_id));
    // Подключаем шаблон
    System::site()->AddTemplatedBox('', 'module/forum_showtopic.html');
    // Выводим блок онлайн
    $online->Render($forum_id, $topic_id, $forum_lang['current_online'], 'forum_online');
    // Предыдущая и следующая тема
    System::site()->AddBlock('forum_prev_topic', isset($prev_topic), false, 'topic');
    if (isset($prev_topic)) {
        System::site()->SetVars('forum_prev_topic', array('url' => Ufu('index.php?name=forum&op=showtopic&topic=' . SafeDB($prev_topic['id'], 11, int), 'forum/topic{topic}.html'), 'title' => SafeDB($prev_topic['title'], 255, str), 'lang_prev_topic' => $forum_lang['prev_topic']));
    }
    System::site()->AddBlock('forum_next_topic', isset($next_topic), false, 'topic');
    if (isset($next_topic)) {
        System::site()->SetVars('forum_next_topic', array('url' => Ufu('index.php?name=forum&op=showtopic&topic=' . SafeDB($next_topic['id'], 11, int), 'forum/topic{topic}.html'), 'title' => SafeDB($next_topic['title'], 255, str), 'lang_next_topic' => $forum_lang['next_topic']));
    }
    // Быстрый переход по форумам
    ForumQuickTransitionBox($forum_id, $forum_lang['quick_transition']);
}
/**
 * Добавляет блок быстрого перехода.
 * @param type $sel_id
 * @param type $title
 * @param type $app_content
 */
function ForumQuickTransitionBox($sel_id, $title = '', $app_content = '')
{
    $data = ForumTree::Instance()->GetCatsDataF($sel_id, true, true);
    $nav_url = 'index.php?name=forum&op=showforum';
    System::site()->AddTextBox('', $app_content . Indent('
		<div style="float:right; white-space:nowrap;" class="forum_quick_transition">
			<table cellspacing="0" cellpadding="0" border="0">
				<tr>
					<th>' . $title . ':&nbsp;</th>
					<td>
						<form action="' . $nav_url . '" method="get">
							<input type="hidden" name="name" value="forum">
							<input type="hidden" name="op" value="showforum">
							' . System::site()->Select('forum', $data, false, 'onchange="this.form.submit();"') . '
						</form>
					</td>
				</tr>
			</table>
		</div>
	'));
}
function IndexForumShowForum()
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Параметры просмотра из GET
    // $forum_id
    // $forum
    // $forum_config
    if (isset($_GET['forum'])) {
        $forum_id = SafeEnv($_GET['forum'], 11, int);
        if (isset($forums_tree->IdCats[$forum_id])) {
            // Проверяем идентификатор форума и загружаем его данные
            $forum = $forums_tree->IdCats[$forum_id];
            // Форум
            $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
            // Конфигурация просматриваемого форума
        } else {
            System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_forum']);
            // Форум не найден
            return;
        }
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_forum']);
        // Нет параметра
        return;
    }
    // Проверяем доступ
    if (!$forum_config['access']) {
        System::site()->AddTextBox($forum_lang['error'], $forum_config['access_reason']);
        // Нет доступа в этот форум
        return;
    }
    // Параметры постраничной навигации
    if (isset($_GET['page'])) {
        $page = SafeEnv($_GET['page'], 11, int);
    } else {
        $page = 1;
    }
    $topics_on_page = System::config('forum/topics_on_page');
    // Устанавливаем заголовок страницы
    System::site()->SetTitle(SafeDB($forum['title'], 255, str) . ' - ' . ($page > 1 ? $forum_lang['page'] . $page . ' - ' : '') . $forum_lang['forum']);
    // Объекты статистики и онлайн
    $statistics = ForumStatistics::Instance();
    $online = ForumOnline::Instance($forum_id);
    // Инициализируем статистику
    $statistics->Initialize($forum_lang['statistics_cat']);
    // Загружаем информацию по топикам в $topics_data и считаем статистику (кэшировать статистику)
    $topics_data = ForumCacheGetTopics();
    // Запрашиваем данные тем (агрегированы по форумам)
    $resolve_cats = $forums_tree->GetAllChildId($forum_id);
    // Считаем только в текущем форуме и всех подфорумах
    foreach ($resolve_cats as $resolve_cat) {
        if (!isset($topics_data[$resolve_cat])) {
            continue;
        }
        foreach ($topics_data[$resolve_cat] as $topic) {
            $statistics->hits += $topic['hits'];
            $statistics->AddTopicAuthor($topic['starter_id'], $topic['starter_name']);
        }
    }
    // Подсчитываем количество тем и постов
    $counters = $forums_tree->GetCountersRecursive($forum_id);
    $statistics->topics_count = $counters['files'];
    $statistics->reply_count = $counters['cats'];
    // Выводим подфорумы с помощью функции main (если есть)
    if (isset($forums_tree->Cats[$forum_id]) && count($forums_tree->Cats[$forum_id]) > 0) {
        ForumLoadFunction('main');
        IndexForumMain($forum_id, $topics_data);
        // <-- IndexForumMain
        // Если просматриваем категорию, то топики не выводим
        if ($forum['parent_id'] == 0) {
            return;
        }
    }
    // Выводим хлебные крошки (нужно после IndexForumMain чтобы не выводились два раза при просмотре категории)
    $forums_tree->BreadCrumbsF($forum_id);
    // Блоки шаблона
    // Ссылки, Отметить все как прочитанные и показать все не прочитанные темы.
    $vars_is_forum_member = array();
    $vars_is_forum_member['url'] = '<a href="' . Ufu('index.php?name=forum&op=markread' . ($forum_id > 0 ? '&forum=' . $forum_id : ''), 'forum/markread/' . ($forum_id > 0 ? '{forum}/' : '')) . '">' . $forum_lang['mark_all_read'] . '</a>';
    $vars_is_forum_member['viewnoreadurl'] = '<a href="' . Ufu('index.php?name=forum&op=viewnoread' . ($forum_id > 0 ? '&forum=' . $forum_id : ''), 'forum/viewnoread/' . ($forum_id > 0 ? '{forum}/' : '')) . '">' . $forum_lang['viewnoread'] . '</a>';
    $vars_is_forum_member['forum_id'] = $forum_id;
    if (!System::site()->HasBlock('is_forum_member')) {
        System::site()->AddBlock('is_forum_member', AccessIsResolved(2), false, 'mark');
    }
    System::site()->SetVars('is_forum_member', $vars_is_forum_member);
    // Последние темы форума
    System::site()->AddBlock('old', true, false, 'mark');
    $vars_old = array();
    $vars_old['lasttopics'] = '<a href="' . Ufu('index.php?name=forum&op=lasttopics&forum=' . $forum_id, 'forum/lasttopics/{forum}/') . '">' . $forum_lang['lasttopics'] . '</a>';
    System::site()->SetVars('old', $vars_old);
    // Заголовки (Темы, Ответов, Просмотры)
    System::site()->AddBlock('statistik', true, false, 'stat');
    $vars_stat = array();
    $vars_stat['count_read'] = '';
    $cat_users_count = $online->GetCatOnlineCount($forum_id);
    if ($cat_users_count > 0) {
        $vars_stat['count_read'] = $cat_users_count > 0 ? '<small> (' . $forum_lang['online'] . ': ' . $cat_users_count . ')</small>' : '';
    }
    System::site()->SetVars('statistik', $vars_stat);
    // Блок с информацией о форуме
    System::site()->AddBlock('forum', true, false);
    System::site()->SetVars('forum', IndexForumDataFilter($forum, $forum_config));
    System::site()->AddBlock('forum_guest_message', true);
    // Блок списка топиков
    System::site()->AddBlock('topics', true, true, 'topic');
    // Инициализируем постраничную навигацию
    $navigation = new Navigation($page);
    $navigation->FrendlyUrl = System::config('general/ufu');
    // Есть ли видимые для пользователя топики
    $visable_topics = false;
    $auth = System::user()->Auth;
    $user_id = System::user()->Get('u_id');
    $is_admin = System::user()->isAdmin();
    if (!isset($topics_data[$forum_id]) || count($topics_data[$forum_id]) == 0) {
        // В этом форуме пока нет ни одной темы
        System::site()->AddBlock('no_topics', true);
        $navigation->DisableNavigation();
    } else {
        // Загружаем данные корзины для видимых топиков
        $basket = ForumBasketGetData('forum_basket_topics');
        // Загружаем данные о прочтении тем
        $read_data = Forum_Marker_GetReadData();
        // Фильтруем топики
        $topics_data = $topics_data[$forum_id];
        // Топики в этом форуме
        $topics = array();
        foreach ($topics_data as $topic) {
            // Добавляем данные из корзины, если топик удалён в корзину (корзину тем видят только админы и пользователи-стартеры удалённых тем)
            $topic['status'] = '';
            $topic['show_delete'] = $is_admin;
            if ($topic['delete'] && isset($basket[$topic['id']]) && $auth && ($is_admin || $topic['starter_id'] == $user_id)) {
                // Добавляем сообщение - "Удалено в корзину"
                $topic['status'] = ForumBasketRender($topic['id'], $topic['title'], $basket, false);
                $topic['show_delete'] = false;
            } elseif ($topic['delete']) {
                continue;
                // Удалён топик и корзина не показывается для этого пользователя
            }
            $topics[] = $topic;
        }
        unset($topics_data);
        // Вывод постраничной навигации
        $navigation->GenNavigationMenu($topics, $topics_on_page, Ufu('index.php?name=forum&op=showforum&forum=' . $forum_id, 'forum/{forum}-{page}/', true));
        // Вывод тем из этой категории с постраничной навигацией
        foreach ($topics as $topic) {
            $close = false;
            if ($forum_config['close']) {
                $close = true;
            }
            // Статус прочитано
            $read = true;
            // прочитано
            if ($auth && (!isset($read_data[$topic['id']]) || $topic['last_post'] > $read_data[$topic['id']]['date'])) {
                $read = false;
            }
            $topic = ForumTopicFilterData($topic);
            // Фильтрация данных топика
            $topic['on'] = !$read;
            $topic['off'] = $read;
            // Закрытие топиков в форуме
            if (!$topic['close']) {
                $topic['close'] = $forum_config['close'];
                $topic['begin'] = !$forum_config['close'];
            }
            $topic['page'] = $page;
            $visable_topics = true;
            System::site()->AddSubBlock('topics', true, $topic);
        }
        System::site()->AddBlock('no_topics', !$visable_topics);
    }
    // Форма добавления топиков
    $show_form = $forum_config['add_topic'] && $auth;
    System::site()->AddBlock('topic_form', $show_form, false, 'form');
    if ($show_form) {
        System::site()->SetVar('topic_form', 'url', Ufu('index.php?name=forum&op=addtopic&forum=' . $forum_id, 'forum/addtopic/{forum}/'));
        ForumSmiliesRender();
        // Подключаем BBCode редактор
        IncludePluginsGroup('bbcode_editors');
    }
    // Блок "Права на форуме"
    System::site()->AddBlock('topic_right', true, false, 'topic', 'module/forum_right.html');
    $right_text = '';
    if ($forum_config['add_topic']) {
        $right_text .= $forum_lang['create_new_topics'] . '<br />';
    } else {
        $right_text .= $forum_lang['no_create_new_topics'] . '<br />';
        $right_text .= '(' . $forum_config['add_topic_reason'] . ')<br />';
    }
    if ($forum_config['add_post']) {
        $right_text .= $forum_lang['create_new_message_in_topics'] . '<br />';
    } else {
        $right_text .= $forum_lang['no_create_new_message_in_topics'] . '<br />';
        $right_text .= '(' . $forum_config['add_post_reason'] . ')<br />';
    }
    System::site()->SetVars('topic_right', array('right' => $right_text));
    // Блоки модерации
    ModerationForumTopicsBlocks();
    // Подключаем шаблон
    System::site()->AddTemplatedBox('', 'module/forum_topics.html');
    // Выводм блок онлайн
    $online->Render($forum_id, '0', $forum_lang['current_category'], 'forum_topics_online');
    // Выводим статистику
    $statistics->Render('forum_topics_statistics');
    // Быстрый переход по форумам
    ForumQuickTransitionBox($forum_id, $forum_lang['quick_transition']);
}
function IndexForumAddTopic()
{
    global $forum_lang;
    $forums_tree = ForumTree::Instance();
    // Проверки на доступ
    if (CheckGet('forum') && CheckPost('topic_title', 'text') && isset($forums_tree->IdCats[$_GET['forum']])) {
        $forum_id = SafeEnv($_GET['forum'], 11, int);
        $forum = $forums_tree->IdCats[$forum_id];
        $forum_config = $forums_tree->GetForumConfigRecursive($forum_id);
        if (!$forum_config['access']) {
            // Доступ
            System::site()->AddTextBox($forum_lang['error'], $forum_config['access_reason']);
            return;
        } elseif (!$forum_config['add_topic']) {
            // Разрешено ли добавлять новые темы
            System::site()->AddTextBox($forum_lang['error'], $forum_config['add_topic_reason']);
            return;
        }
    } else {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_data']);
        return;
    }
    if (!CheckPost('text') || strlen($_POST['text']) == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['no_data']);
        return;
    }
    $user_id = System::user()->Get('u_id');
    $user_name = System::user()->Get('u_name');
    $time = time();
    // Добавляем топик
    // TODO: Зачем здесь пустое поле?
    $uniq_code = '';
    //GenRandomString(12, '1234567890');
    $topic_title = SafeEnv($_POST['topic_title'], 255, str);
    if (strlen($topic_title) == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['no_title_topic']);
        return;
    }
    $topic_values = Values('', $forum_id, $topic_title, '1', '0', '0', $time, $user_id, $user_name, $time, '0', '', $uniq_code, 0, 0, 0);
    System::database()->Insert('forum_topics', $topic_values);
    $topic_id = System::database()->GetLastId();
    $topic = System::database()->Select('forum_topics', "`id`='{$topic_id}'");
    $topic = $topic[0];
    // Добавляем сообщение
    $email = System::user()->Get('u_email');
    $hideemail = System::user()->Get('u_hideemail');
    $site = System::user()->Get('u_homepage');
    $icq = System::user()->Get('u_icq');
    $text = SafeEnv($_POST['text'], 0, str);
    System::database()->Insert('forum_posts', Values('', $topic_id, $user_id, time(), $user_name, $site, $email, $hideemail, $icq, $text, getip(), 0));
    // Добавляем очков пользователю
    System::user()->ChargePoints(System::config('points/forum_post'));
    // Увеличиваем счётчик сообщений и тем пользователя
    ForumCalcUserCounters(1, 1);
    $forum['topics'] = SafeDB($forum['topics'], 11, int) + 1;
    IndexForumSetLastPostInfo($forum, $topic);
    // Добавляем метку о прочтении темы автором топика
    System::database()->Insert('forum_topics_read', Values($user_id, $topic_id, $time));
    // Очищаем кэш
    ForumCacheClear();
    GO(Ufu('index.php?name=forum&op=showforum&forum=' . $forum_id, GetSiteUrl() . 'forum/{forum}/'));
}
<?php

/*
 * LinkorCMS 1.4
 * © 2012 LinkorCMS Development Group
 */
if (!defined('VALID_RUN')) {
    header("HTTP/1.1 404 Not Found");
    exit;
}
include_once System::config('mod_dir') . 'forum/lib/functions.php';
include_once System::config('mod_dir') . 'forum/lib/forum_tree.class.php';
global $sitemap_show_objects, $forums_tree, $sitemap_forum_topics;
$sitemap_show_objects = System::config('general/sitemap_show_objects') ? '___SitemapPluginForumTopics' : null;
$forums_tree = ForumTree::Instance();
$sitemap_forum_topics = array();
// Загружаем темы
if (isset($sitemap_show_objects)) {
    $forum_topics = System::database()->Select('forum_topics', "`delete` = '0'", null, 'start_date');
    // Только включенные и доступные гостям
    foreach ($forum_topics as $topic) {
        $sitemap_forum_topics[$topic['forum_id']][] = array($topic['title'], Ufu('index.php?name=forum&op=showtopic&topic=' . SafeDB($topic['id'], 11, int), 'forum/topic{topic}.html'));
    }
    unset($forum_topics);
}
function ___SitemapPluginForum($Forum, $Level, $i, $c)
{
    global $forums_tree;
    $forum_config = $forums_tree->GetForumConfigRecursive($Forum['id'], ACCESS_ALL);
    if (!$forum_config['access']) {
        return false;
function AdminForumEditor()
{
    $site = System::site();
    $f_title = '';
    $f_desc = '';
    if (CheckGet('parent')) {
        $f_parent = SafeDB($_GET['parent'], 11, int);
    } else {
        $f_parent = 0;
    }
    $f_view = 4;
    $f_status = 1;
    $f_admin_theme_add = array(false, false);
    $f_new_message_email = array(false, true);
    $f_no_link_guest = array(false, false);
    $rang_access = 0;
    $rang_add_theme = 0;
    $rang_message = 0;
    $close_topic = array(false, false);
    if (isset($_GET['id'])) {
        // Редактирование
        $id = SafeDB($_GET['id'], 11, int);
        System::database()->Select('forums', "`id`='{$id}'");
        $forum = System::database()->FetchRow();
        $f_title = SafeDB($forum['title'], 255, str);
        $f_desc = SafeDB($forum['description'], 0, str);
        $f_parent = SafeDB($forum['parent_id'], 11, int);
        $f_admin_theme_add[(int) $forum['admin_theme_add']] = true;
        $f_new_message_email[(int) $forum['new_message_email']] = true;
        $f_no_link_guest[(int) $forum['no_link_guest']] = true;
        $rang_access = SafeDB($forum['rang_access'], 11, int);
        $rang_add_theme = SafeDB($forum['rang_add_theme'], 11, int);
        $rang_message = SafeDB($forum['rang_message'], 11, int);
        $close_topic[(int) $forum['close_topic']] = true;
        $f_view = SafeDB($forum['view'], 1, int);
        $f_status = SafeDB($forum['status'], 1, int);
        $id_param = '&id=' . $id;
        $b_cap = 'Сохранить изменения';
        if ($f_parent == 0) {
            $c_cap = 'Редактирование категории';
        } else {
            $c_cap = 'Редактирование форума';
        }
    } else {
        // Добавление
        $f_title = '';
        $f_admin_theme_add[0] = true;
        $f_new_message_email[1] = true;
        $f_no_link_guest[0] = true;
        $close_topic[0] = true;
        $id_param = '';
        $b_cap = 'Добавить';
        if ($f_parent == 0) {
            $c_cap = 'Добавить категорию';
        } else {
            $c_cap = 'Добавить форум';
        }
    }
    FormRow('Название', $site->Edit('title', $f_title, false, 'style="width:400px;" maxlength="255" class="autofocus"'));
    if ($f_parent != 0) {
        $where = '';
        if (isset($_GET['id'])) {
            $where = " `id`<>'" . SafeEnv($_GET['id'], 11, int) . "'";
        }
        $forums = System::database()->Select('forums', $where);
        $cat = false;
        if (count($forums) == 0) {
            $cat = false;
        } else {
            foreach ($forums as $forum) {
                if ($forum['parent_id'] == 0) {
                    $cat = true;
                }
            }
        }
        SortArray($forums, 'order');
        $tree = ForumTree::Instance($forums);
        $tree->NumItemsCaption = '';
        $tree->TopCatName = 'Нет родительского раздела';
        $data = array();
        if ($cat) {
            $data = $tree->GetCatsDataF($f_parent, true, true);
        } else {
            $site->DataAdd($data, 0, $tree->TopCatName, true);
        }
        FormRow('Родительский раздел', $site->Select('sub_id', $data));
        FormTextRow('Описание', $site->HtmlEditor('desc', $f_desc, 600, 200));
    }
    System::admin()->FormTitleRow('Настройки форума');
    $endata = array();
    $site->DataAdd($endata, '1', 'Да', $f_admin_theme_add[1]);
    $site->DataAdd($endata, '0', 'Нет', $f_admin_theme_add[0]);
    FormRow('', 'Только администраторы могут создавать новые темы: ' . $site->Select('admin_theme_add', $endata));
    $endata = array();
    $site->DataAdd($endata, '1', 'Да', $f_no_link_guest[1]);
    $site->DataAdd($endata, '0', 'Нет', $f_no_link_guest[0]);
    FormRow('', 'Скрывать ссылки от гостей: ' . $site->Select('no_link_guest', $endata));
    $endata = array();
    $site->DataAdd($endata, '1', 'Да', $f_new_message_email[1]);
    $site->DataAdd($endata, '0', 'Нет', $f_new_message_email[0]);
    FormRow('', 'Разрешить подписку на уведомление о новых сообщениях в теме: ' . $site->Select('new_message_email', $endata));
    $endata = array();
    $site->DataAdd($endata, '1', 'Да', $close_topic[1]);
    $site->DataAdd($endata, '0', 'Нет', $close_topic[0]);
    FormRow('', 'Закрыть для обсуждения (будет доступен только просмотр): ' . $site->Select('close_topic', $endata));
    System::admin()->FormTitleRow('Настройка прав доступа по рангам пользователей');
    FormRow('Доступ (с меньшим рангом доступ будет закрыт)', ForumAdminGetUsersTypesComboBox('rang_access', $rang_access));
    FormRow('Создание тем (с меньшим рангом темы создавать будет запрещено)', ForumAdminGetUsersTypesComboBox('rang_add_theme', $rang_add_theme));
    FormRow('Создание сообщений в теме (с меньшим рангом сообщения создавать будет запрещено)', ForumAdminGetUsersTypesComboBox('rang_message', $rang_message));
    System::admin()->FormTitleRow('Параметры видимости');
    FormRow('Видят', $site->Select('view', GetUserTypesFormData($f_view)));
    FormRow('Включить', $site->Select('status', GetEnData($f_status, 'Да', 'Нет')));
    FormRow('Внимание', 'Ограничения прав и видимости действует на все дочерние форумы.');
    AddCenterBox($c_cap);
    AddForm($site->FormOpen(ADMIN_FILE . '?exe=forum&a=forum_save' . $id_param), $site->Submit($b_cap));
}
function ForumModerationMoveTopics($topics, $begin)
{
    global $forum_lang;
    if (!$begin) {
        $topics = System::database()->Select('forum_topics', '`id`=\'' . implode('\' or `id`=\'', $topics) . '\'');
        $forum_id = $topics[0]['forum_id'];
        $text = $forum_lang['confirm'] . ':&nbsp;' . $forum_lang['move_topics'];
        $text .= '<ul style="margin: 10px 0;">';
        foreach ($topics as $topic) {
            $text .= '<li>' . SafeDB($topic['title'], 255, str) . '</li>';
        }
        $text .= '</ul>';
        $data = ForumTree::Instance()->GetCatsDataF($forum_id, false, false, 0, true);
        $text .= $forum_lang['select_category'] . ': <br>' . System::site()->Select('forum', $data) . '<br><br>';
        return $text;
    }
    // Перемещение тем (темы из одного форума)
    $dst_forum_id = SafeEnv($_POST['forum'], 11, int);
    // Куда перемещаем
    System::database()->Select('forums', "`id`='{$dst_forum_id}'");
    if (System::database()->NumRows() == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_forum']);
        return false;
    }
    $dst_forum = System::database()->FetchRow();
    if (count($topics) == 0) {
        System::site()->AddTextBox($forum_lang['error'], $forum_lang['error_no_topic']);
        return false;
    }
    $move_topics = System::database()->Select('forum_topics', '`id`=\'' . implode('\' or `id`=\'', $topics) . '\'');
    $src_forum_id = SafeEnv($move_topics[0]['forum_id'], 11, int);
    System::database()->Select('forums', "`id`='{$src_forum_id}'");
    $src_forum = System::database()->FetchRow();
    // Меняем у тем форум
    System::database()->Update('forum_topics', "`forum_id`='{$dst_forum_id}'", '`id`=\'' . implode('\' or `id`=\'', $topics) . '\'');
    // Очищаем кэш форума
    ForumCacheClear();
    // Подсчитываем количество перемещаемых тем и сообщений
    $moved_topics = count($move_topics);
    $moved_posts = 0;
    foreach ($move_topics as $topic) {
        $moved_posts += $topic['posts'];
    }
    // Устанавливаем информацию о последнем посте в форуме (исходный форум)
    $forum_topics = (int) $src_forum['topics'] - $moved_topics;
    $forum_posts = (int) $src_forum['posts'] - $moved_posts;
    if ($forum_topics < 0) {
        $forum_topics = 0;
    }
    if ($forum_posts < 0) {
        $forum_posts = 0;
    }
    ForumSetLastTopic($src_forum_id, "`topics`='{$forum_topics}',`posts`='{$forum_posts}'");
    // Устанавливаем информацию о последнем посте в форуме (форум назначения)
    $forum_topics = (int) $dst_forum['topics'] + $moved_topics;
    $forum_posts = (int) $dst_forum['posts'] + $moved_posts;
    if ($forum_topics < 0) {
        $forum_topics = 0;
    }
    if ($forum_posts < 0) {
        $forum_posts = 0;
    }
    ForumSetLastTopic($dst_forum_id, "`topics`='{$forum_topics}',`posts`='{$forum_posts}'");
    // Очищаем кэш форума
    ForumCacheClear();
}