2017-09-30
This commit is contained in:
parent
7362c03c7a
commit
58b807cb87
18 changed files with 891 additions and 151 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -2,8 +2,4 @@
|
|||
/app/config/main.php
|
||||
/app/cache/**/*.php
|
||||
/app/cache/**/*.lock
|
||||
/img/avatars/*
|
||||
!/img/avatars/index.html
|
||||
/img/members/*
|
||||
!/img/members/.htaccess
|
||||
!/img/members/nofile.gif
|
||||
/public/avatar/*
|
||||
|
|
|
@ -82,8 +82,10 @@ class Routing
|
|||
$r->add('GET', '/forum/{id:[1-9]\d*}[/{name}][/page/{page:[1-9]\d*}]', 'Forum:view', 'Forum');
|
||||
// темы
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}[/{name}][/page/{page:[1-9]\d*}]', 'Topic:view', 'Topic');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/go_to/new', 'Topic:goToNew', 'TopicGoToNew');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/go_to/unread', 'Topic:goToUnread', 'TopicGoToUnread');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/new', 'Topic:goToNew', 'TopicGoToNew');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/unread', 'Topic:goToUnread', 'TopicGoToUnread');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/last', 'Topic:goToLast', 'TopicGoToLast');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/new/post', 'Post:new', 'NewPost');
|
||||
// сообщения
|
||||
$r->add('GET', '/post/{id:[1-9]\d*}#p{id}', 'Topic:viewPost', 'ViewPost'); //????
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class Container
|
|||
if (is_array($service)) {
|
||||
return $this->fromArray($service, $tree);
|
||||
} elseif (is_object($service)) {
|
||||
return $service->$tree[0];
|
||||
return $service->{$tree[0]};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,6 @@ class Func
|
|||
}
|
||||
if ($i === $cur) {
|
||||
$pages[] = [null, $i, true];
|
||||
} elseif ($i === 1) {
|
||||
$pages[] = [$this->c->Router->link($marker, $args), $i, null];
|
||||
} else {
|
||||
$pages[] = [$this->c->Router->link($marker, ['page' => $i] + $args), $i, null];
|
||||
}
|
||||
|
|
|
@ -97,13 +97,15 @@ class Router
|
|||
*/
|
||||
public function link($marker = null, array $args = [])
|
||||
{
|
||||
$result = $this->baseUrl; //???? http и https
|
||||
$result = $this->baseUrl;
|
||||
if (is_string($marker) && isset($this->links[$marker])) {
|
||||
$s = $this->links[$marker];
|
||||
foreach ($args as $key => $val) {
|
||||
if ($key == '#') {
|
||||
$s .= '#' . rawurlencode($val); //????
|
||||
continue;
|
||||
} elseif ($key == 'page' && $val === 1) {
|
||||
continue;
|
||||
}
|
||||
$s = preg_replace(
|
||||
'%\{' . preg_quote($key, '%') . '(?::[^{}]+)?\}%',
|
||||
|
|
|
@ -79,7 +79,7 @@ class Forum extends Page
|
|||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$offset = $user->dispTopics * ($page - 1);
|
||||
$offset = ($page - 1) * $user->dispTopics;
|
||||
|
||||
switch ($curForum['sort_by']) {
|
||||
case 1:
|
||||
|
@ -132,10 +132,7 @@ class Forum extends Page
|
|||
$topics = $this->c->DB->query($sql, $vars)->fetchAll();
|
||||
|
||||
foreach ($topics as &$cur) {
|
||||
// цензура
|
||||
if ($this->config['o_censoring'] == '1') {
|
||||
$cur['subject'] = preg_replace($this->c->censoring[0], $this->c->censoring[1], $cur['subject']);
|
||||
}
|
||||
$cur['subject'] = $this->censor($cur['subject']);
|
||||
// перенос темы
|
||||
if ($cur['moved_to']) {
|
||||
$cur['link'] = $this->c->Router->link('Topic', ['id' => $cur['moved_to'], 'name' => $cur['subject']]);
|
||||
|
@ -155,8 +152,8 @@ class Forum extends Page
|
|||
|
||||
$cur['link'] = $this->c->Router->link('Topic', ['id' => $cur['id'], 'name' => $cur['subject']]);
|
||||
$cur['link_last'] = $this->c->Router->link('ViewPost', ['id' => $cur['last_post_id']]);
|
||||
$cur['num_views'] = $this->config['o_topic_views'] == '1' ? $this->number($cur['num_views']) : null;
|
||||
$cur['num_replies'] = $this->number($cur['num_replies']);
|
||||
$cur['views'] = $this->config['o_topic_views'] == '1' ? $this->number($cur['num_views']) : null;
|
||||
$cur['replies'] = $this->number($cur['num_replies']);
|
||||
$time = $cur['last_post'];
|
||||
$cur['last_post'] = $this->time($cur['last_post']);
|
||||
// для гостя пусто
|
||||
|
@ -191,6 +188,7 @@ class Forum extends Page
|
|||
|| ($user->isAdmMod && isset($moders[$user->id]));
|
||||
|
||||
$this->onlinePos = 'forum-' . $args['id'];
|
||||
|
||||
$crumbs = [];
|
||||
$id = $args['id'];
|
||||
$activ = true;
|
||||
|
@ -223,8 +221,8 @@ class Forum extends Page
|
|||
'pages' => $this->c->Func->paginate($pages, $page, 'Forum', ['id' => $args['id'], 'name' => $fDesc[$args['id']]['forum_name']]),
|
||||
];
|
||||
|
||||
$this->canonical = $page > 1 ? $this->c->Router->link('Forum', ['id' => $args['id'], 'name' => $fDesc[$args['id']]['forum_name'], 'page' => $page])
|
||||
: $this->c->Router->link('Forum', ['id' => $args['id'], 'name' => $fDesc[$args['id']]['forum_name']]);
|
||||
$this->canonical = $this->c->Router->link('Forum', ['id' => $args['id'], 'name' => $fDesc[$args['id']]['forum_name'], 'page' => $page]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -407,6 +407,20 @@ abstract class Page
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет цензуру при необходимости
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
protected function censor($str)
|
||||
{
|
||||
if ($this->config['o_censoring'] == '1') {
|
||||
return (string) preg_replace($this->c->censoring[0], $this->c->censoring[1], $str);
|
||||
} else {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Заглушка
|
||||
* @param string $name
|
||||
|
|
|
@ -115,9 +115,7 @@ class Register extends Page
|
|||
if (preg_match('%^(guest|' . preg_quote(__('Guest'), '%') . ')$%iu', $username)) {
|
||||
$error = __('Username guest');
|
||||
// цензура
|
||||
} elseif ($this->config['o_censoring'] == '1'
|
||||
&& preg_replace($this->c->censoring[0], $this->c->censoring[1], $username) !== $username
|
||||
) {
|
||||
} elseif ($this->censor($username) !== $username) {
|
||||
$error = __('Username censor');
|
||||
// username забанен
|
||||
} elseif ($this->c->CheckBans->isBanned($username) > 0) {
|
||||
|
|
338
app/Models/Pages/Topic.php
Normal file
338
app/Models/Pages/Topic.php
Normal file
|
@ -0,0 +1,338 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
class Topic extends Page
|
||||
{
|
||||
use UsersTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'topic';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'topic';
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function goToNew(array $args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function goToUnread(array $args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Переход к последнему сообщению темы
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function goToLast(array $args)
|
||||
{
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
];
|
||||
$sql = 'SELECT MAX(id) FROM ::posts WHERE topic_id=?i:tid';
|
||||
|
||||
$pid = $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
// нет ни одного сообщения в теме
|
||||
if (empty($pid)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
return $this->c->Redirect->setPage('ViewPost', ['id' => $pid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр темы по номеру сообщения
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function viewPost(array $args)
|
||||
{
|
||||
$vars = [
|
||||
':pid' => $args['id'],
|
||||
];
|
||||
$sql = 'SELECT topic_id FROM ::posts WHERE id=?i:pid';
|
||||
|
||||
$tid = $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
// сообшение не найдено в базе
|
||||
if (empty($tid)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':pid' => $args['id'],
|
||||
':tid' => $tid,
|
||||
];
|
||||
$sql = 'SELECT COUNT(id) FROM ::posts WHERE topic_id=?i:tid AND id<?i:pid';
|
||||
|
||||
$num = 1 + $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
return $this->view([
|
||||
'id' => $tid,
|
||||
'page' => ceil($num / $this->c->user->dispPosts),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function view(array $args)
|
||||
{
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
$user = $this->c->user;
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':uid' => $user->id,
|
||||
];
|
||||
|
||||
if ($user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
WHERE t.id=?i:tid AND t.moved_to IS NULL';
|
||||
} else {
|
||||
$sql = 'SELECT t.*, f.moderators, s.user_id AS is_subscribed
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
|
||||
WHERE t.id=?i:tid AND t.moved_to IS NULL';
|
||||
}
|
||||
$topic = $this->c->DB->query($sql, $vars)->fetch();
|
||||
|
||||
// тема отсутствует или недоступна
|
||||
if (empty($topic)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
// раздел отсутствует в доступных
|
||||
if (empty($fDesc[$topic['forum_id']])) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
$pages = ceil(( $topic['num_replies'] + 1) / $user->dispPosts);
|
||||
|
||||
// попытка открыть страницу которой нет
|
||||
if ($page < 1 || $page > $pages) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $user->dispPosts;
|
||||
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':offset' => $offset,
|
||||
':rows' => $user->dispPosts,
|
||||
];
|
||||
$sql = 'SELECT id
|
||||
FROM ::posts
|
||||
WHERE topic_id=?i:tid
|
||||
ORDER BY id LIMIT ?i:offset, ?i:rows';
|
||||
$ids = $this->c->DB->query($sql, $vars)->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
// нарушена синхронизация количества сообщений в темах
|
||||
if (empty($ids)) {
|
||||
return $this->goToLast($args); //????
|
||||
}
|
||||
|
||||
$moders = empty($topic['moderators']) ? [] : array_flip(unserialize($topic['moderators']));
|
||||
|
||||
$parent = isset($fDesc[$topic['forum_id']][0]) ? $fDesc[$topic['forum_id']][0] : 0;
|
||||
$perm = $fTree[$parent][$topic['forum_id']];
|
||||
|
||||
if ($user->isAdmin) {
|
||||
$newPost = $this->c->Router->link('NewPost', ['id' => $args['id']]);
|
||||
} elseif ($topic['closed'] == '1') {
|
||||
$newPost = false;
|
||||
} elseif ($perm['post_replies'] === 1
|
||||
|| (null === $perm['post_replies'] && $user->gPostReplies == '1')
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]))
|
||||
) {
|
||||
$newPost = $this->c->Router->link('NewPost', ['id' => $args['id']]);
|
||||
} else {
|
||||
$newPost = null;
|
||||
}
|
||||
|
||||
// приклейка первого сообщения темы
|
||||
$stickFP = (! empty($topic['stick_fp']) || ! empty($topic['poll_type']));
|
||||
if ($stickFP) {
|
||||
$ids[] = $topic['first_post_id'];
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':ids' => $ids,
|
||||
];
|
||||
$sql = 'SELECT id, message, poster, posted
|
||||
FROM ::warnings
|
||||
WHERE id IN (?ai:ids)';
|
||||
$warnings = $this->c->DB->query($sql, $vars)->fetchAll(\PDO::FETCH_GROUP);
|
||||
|
||||
$vars = [
|
||||
':ids' => $ids,
|
||||
];
|
||||
$sql = 'SELECT u.warning_all, u.gender, u.email, u.title, u.url, u.location, u.signature,
|
||||
u.email_setting, u.num_posts, u.registered, u.admin_note, u.messages_enable,
|
||||
p.id, p.poster as username, p.poster_id, p.poster_ip, p.poster_email, p.message,
|
||||
p.hide_smilies, p.posted, p.edited, p.edited_by, p.edit_post, p.user_agent,
|
||||
g.g_id, g.g_user_title, g.g_promote_next_group, g.g_pm
|
||||
FROM ::posts AS p
|
||||
INNER JOIN ::users AS u ON u.id=p.poster_id
|
||||
INNER JOIN ::groups AS g ON g.g_id=u.group_id
|
||||
WHERE p.id IN (?ai:ids) ORDER BY p.id';
|
||||
$stmt = $this->c->DB->query($sql, $vars);
|
||||
|
||||
$genders = [1 => ' f-user-male', 2 => ' f-user-female'];
|
||||
$postCount = 0;
|
||||
$posts = [];
|
||||
$posters = [];
|
||||
while ($cur = $stmt->fetch()) {
|
||||
// данные по автору сообшения
|
||||
if (isset($posters[$cur['poster_id']])) {
|
||||
$post = $posters[$cur['poster_id']];
|
||||
} else {
|
||||
$post = [
|
||||
'poster' => $cur['username'],
|
||||
'poster_title' => $this->censor($this->userGetTitle($cur)),
|
||||
'poster_avatar' => null,
|
||||
'poster_registered' => null,
|
||||
'poster_location' => null,
|
||||
'poster_info_add' => false,
|
||||
'poster_link' => null,
|
||||
'poster_posts' => null,
|
||||
'poster_gender' => '',
|
||||
'poster_online' => '',
|
||||
|
||||
];
|
||||
if ($cur['poster_id'] > 1) {
|
||||
if ($user->gViewUsers == '1') {
|
||||
$post['poster_link'] = $this->c->Router->link('User', ['id' => $cur['poster_id'], 'name' => $cur['username']]);
|
||||
}
|
||||
if ($this->config['o_avatars'] == '1' && $user->showAvatars == '1') {
|
||||
$post['poster_avatar'] = $this->userGetAvatarLink($cur['poster_id']);
|
||||
}
|
||||
if ($this->config['o_show_user_info'] == '1') {
|
||||
$post['poster_info_add'] = true;
|
||||
|
||||
$post['poster_registered'] = $this->time($cur['registered'], true);
|
||||
|
||||
$post['poster_posts'] = $this->number($cur['num_posts']);
|
||||
$post['poster_num_posts'] = $cur['num_posts'];
|
||||
|
||||
if ($cur['location'] != '') {
|
||||
$post['poster_location'] = $this->censor($cur['location']);
|
||||
}
|
||||
if (isset($genders[$cur['gender']])) {
|
||||
$post['poster_gender'] = $genders[$cur['gender']];
|
||||
}
|
||||
}
|
||||
$post['poster_online'] = ' f-user-online'; //????
|
||||
|
||||
$posters[$cur['poster_id']] = $post;
|
||||
}
|
||||
}
|
||||
|
||||
// данные по сообщению
|
||||
$post['id'] = $cur['id'];
|
||||
$post['link'] = $this->c->Router->link('ViewPost', ['id' => $cur['id']]);
|
||||
$post['posted'] = $this->time($cur['posted']);
|
||||
$post['posted_utc'] = gmdate('Y-m-d\TH:i:s\Z', $cur['posted']);
|
||||
|
||||
// номер сообшения в теме
|
||||
if ($stickFP && $offset > 0 && $cur['id'] == $topic['first_post_id']) {
|
||||
$post['post_number'] = 1;
|
||||
} else {
|
||||
++$postCount;
|
||||
$post['post_number'] = $offset + $postCount;
|
||||
}
|
||||
|
||||
// данные по элементам управления
|
||||
$controls = [];
|
||||
if (! $user->isAdmin && ! $user->isGuest) {
|
||||
$controls['report'] = ['#', 'Report'];
|
||||
}
|
||||
if ($user->isAdmin
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]))
|
||||
|| ($cur['poster_id'] == $user->id) //????
|
||||
) {
|
||||
$controls['edit'] = ['#', 'Edit'];
|
||||
}
|
||||
if ($newPost) {
|
||||
$controls['quote'] = ['#', 'Reply'];
|
||||
}
|
||||
|
||||
$post['controls'] = $controls;
|
||||
|
||||
$posts[] = $post;
|
||||
}
|
||||
|
||||
$topic['subject'] = $this->censor($topic['subject']);
|
||||
|
||||
$crumbs = [];
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Topic', ['id' => $args['id'], 'name' => $topic['subject']]),
|
||||
$topic['subject'],
|
||||
true,
|
||||
];
|
||||
$this->titles[] = $topic['subject'];
|
||||
|
||||
$id = $topic['forum_id'];
|
||||
$activ = null;
|
||||
while (true) {
|
||||
$name = $fDesc[$id]['forum_name'];
|
||||
$this->titles[] = $name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $id, 'name' => $name]),
|
||||
$name,
|
||||
$activ,
|
||||
];
|
||||
$activ = null;
|
||||
if (! isset($fDesc[$id][0])) {
|
||||
break;
|
||||
}
|
||||
$id = $fDesc[$id][0];
|
||||
}
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Index'),
|
||||
__('Index'),
|
||||
null,
|
||||
];
|
||||
|
||||
$this->data = [
|
||||
'topic' => $topic,
|
||||
'posts' => $posts,
|
||||
'warnings' => $warnings,
|
||||
'crumbs' => array_reverse($crumbs),
|
||||
'topicName' => $topic['subject'],
|
||||
'newPost' => $newPost,
|
||||
'stickFP' => $stickFP,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, 'Topic', ['id' => $args['id'], 'name' => $topic['subject']]),
|
||||
];
|
||||
|
||||
$this->canonical = $this->c->Router->link('Topic', ['id' => $args['id'], 'name' => $topic['subject'], 'page' => $page]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
59
app/Models/Pages/UsersTrait.php
Normal file
59
app/Models/Pages/UsersTrait.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
trait UsersTrait
|
||||
{
|
||||
/**
|
||||
* Имена забаненных пользователей
|
||||
* @var array
|
||||
*/
|
||||
protected $userBanNames;
|
||||
|
||||
/**
|
||||
* Определение титула для пользователя
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
protected function userGetTitle(array $data)
|
||||
{
|
||||
if (! isset($this->userBanNames)) {
|
||||
$this->userBanNames = [];
|
||||
foreach($this->c->bans as $cur) {
|
||||
$this->userBanNames[mb_strtolower($cur['username'])] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($this->userBanNames[$data['username']])) {
|
||||
return __('Banned');
|
||||
} elseif ($data['title'] != '') {
|
||||
return $data['title'];
|
||||
} elseif ($data['g_user_title'] != '') {
|
||||
return $data['g_user_title'];
|
||||
} elseif ($data['g_id'] == $this->c->GROUP_GUEST) {
|
||||
return __('Guest');
|
||||
} else {
|
||||
return __('Member');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Определение ссылки на аватарку
|
||||
* @param int $id
|
||||
* @return string|null
|
||||
*/
|
||||
protected function userGetAvatarLink($id)
|
||||
{
|
||||
$filetypes = array('jpg', 'gif', 'png');
|
||||
|
||||
foreach ($filetypes as $type) {
|
||||
$path = $this->c->DIR_PUBLIC . "/avatar/{$id}.{$type}";
|
||||
|
||||
if (file_exists($path) && getimagesize($path)) {
|
||||
return $this->c->PUBLIC_URL . "/avatar/{$id}.{$type}";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -31,6 +31,14 @@ if (file_exists(__DIR__ . '/config/main.php')) {
|
|||
|
||||
require __DIR__ . '/functions.php';
|
||||
|
||||
// https or http?
|
||||
if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
|
||||
$c->BASE_URL = str_replace('http://', 'https://', $c->BASE_URL);
|
||||
} else {
|
||||
$c->BASE_URL = str_replace('https://', 'http://', $c->BASE_URL);
|
||||
}
|
||||
$c->PUBLIC_URL = $c->BASE_URL . $forkPublicPrefix;
|
||||
|
||||
$c->FORK_REVISION = 1;
|
||||
$c->START = $forkStart;
|
||||
$c->DIR_APP = __DIR__;
|
||||
|
@ -52,7 +60,7 @@ if ($page->getDataForOnline(true)) {
|
|||
$c->Online->handle($page);
|
||||
}
|
||||
$tpl = $c->View->rendering($page);
|
||||
if ($c->DEBUG > 0) {
|
||||
if ($tpl !== null && $c->DEBUG > 0) {
|
||||
$debug = $c->Debug->debug();
|
||||
$debug = $c->View->rendering($debug);
|
||||
$tpl = str_replace('<!-- debuginfo -->', $debug, $tpl);
|
||||
|
|
|
@ -12,7 +12,7 @@ function __($data, ...$args)
|
|||
$tr = $lang->get($data);
|
||||
|
||||
if (is_array($tr)) {
|
||||
if (isset($args[0]) && is_numeric($args[0])) {
|
||||
if (isset($args[0]) && is_int($args[0])) {
|
||||
$n = array_shift($args);
|
||||
eval('$n = (int) ' . $tr['plural']);
|
||||
$tr = $tr[$n];
|
||||
|
|
102
app/lang/English/topic.po
Normal file
102
app/lang/English/topic.po
Normal file
|
@ -0,0 +1,102 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Project-Id-Version: ForkBB\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: ForkBB <mio.visman@yandex.ru>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: en\n"
|
||||
|
||||
msgid "Post reply"
|
||||
msgstr "Post reply"
|
||||
|
||||
msgid "Topic closed"
|
||||
msgstr "Topic closed"
|
||||
|
||||
msgid "From"
|
||||
msgstr "From:"
|
||||
|
||||
msgid "Promote user"
|
||||
msgstr "Promote user"
|
||||
|
||||
msgid "IP address logged"
|
||||
msgstr "IP address logged"
|
||||
|
||||
msgid "Note"
|
||||
msgstr "Note:"
|
||||
|
||||
msgid "%s post"
|
||||
msgid_plural "%s posts"
|
||||
msgstr[0] "%s post"
|
||||
msgstr[1] "%s posts"
|
||||
|
||||
msgid "Registered:"
|
||||
msgstr "Registered:"
|
||||
|
||||
msgid "Replies"
|
||||
msgstr "Replies:"
|
||||
|
||||
msgid "Website"
|
||||
msgstr "Website"
|
||||
|
||||
msgid "Online"
|
||||
msgstr "Online"
|
||||
|
||||
msgid "Offline"
|
||||
msgstr "Offline"
|
||||
|
||||
msgid "Last edit"
|
||||
msgstr "Last edited by"
|
||||
|
||||
msgid "Report"
|
||||
msgstr "Report"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
msgid "Quote"
|
||||
msgstr "Quote"
|
||||
|
||||
msgid "Is subscribed"
|
||||
msgstr "You are currently subscribed to this topic"
|
||||
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Unsubscribe"
|
||||
|
||||
msgid "Subscribe"
|
||||
msgstr "Subscribe to this topic"
|
||||
|
||||
msgid "Quick post"
|
||||
msgstr "Quick reply"
|
||||
|
||||
msgid "Mod controls"
|
||||
msgstr "Moderator controls"
|
||||
|
||||
msgid "New icon"
|
||||
msgstr "New post"
|
||||
|
||||
msgid "Re"
|
||||
msgstr "Re:"
|
||||
|
||||
msgid "Preview"
|
||||
msgstr "Preview"
|
||||
|
||||
msgid "Warnings"
|
||||
msgstr "Warnings:"
|
||||
|
||||
msgid "Reply"
|
||||
msgstr "Reply"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Registered users online in this topic: %s"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "guests: %s"
|
103
app/lang/Russian/topic.po
Normal file
103
app/lang/Russian/topic.po
Normal file
|
@ -0,0 +1,103 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"Project-Id-Version: ForkBB\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: ForkBB <mio.visman@yandex.ru>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru\n"
|
||||
|
||||
msgid "Post reply"
|
||||
msgstr "Ответить"
|
||||
|
||||
msgid "Topic closed"
|
||||
msgstr "Тема закрыта"
|
||||
|
||||
msgid "From"
|
||||
msgstr "Откуда:"
|
||||
|
||||
msgid "Promote user"
|
||||
msgstr "Переместить пользователя"
|
||||
|
||||
msgid "IP address logged"
|
||||
msgstr "IP адрес"
|
||||
|
||||
msgid "Note"
|
||||
msgstr "Замечание"
|
||||
|
||||
msgid "%s post"
|
||||
msgid_plural "%s posts"
|
||||
msgstr[0] "%s сообщение"
|
||||
msgstr[1] "%s сообщения"
|
||||
msgstr[2] "%s сообщений"
|
||||
|
||||
msgid "Registered:"
|
||||
msgstr "Здесь с"
|
||||
|
||||
msgid "Replies"
|
||||
msgstr "Ответов:"
|
||||
|
||||
msgid "Website"
|
||||
msgstr "Сайт"
|
||||
|
||||
msgid "Online"
|
||||
msgstr "Активен"
|
||||
|
||||
msgid "Offline"
|
||||
msgstr "Вне форума"
|
||||
|
||||
msgid "Last edit"
|
||||
msgstr "Отредактировано"
|
||||
|
||||
msgid "Report"
|
||||
msgstr "Просигналить"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "Редактировать"
|
||||
|
||||
msgid "Quote"
|
||||
msgstr "Цитировать"
|
||||
|
||||
msgid "Is subscribed"
|
||||
msgstr "Вы подписаны на эту тему"
|
||||
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Отказаться от подписки"
|
||||
|
||||
msgid "Subscribe"
|
||||
msgstr "Подписаться на тему"
|
||||
|
||||
msgid "Quick post"
|
||||
msgstr "Быстрый ответ"
|
||||
|
||||
msgid "Mod controls"
|
||||
msgstr "Операции модерирования"
|
||||
|
||||
msgid "New icon"
|
||||
msgstr "New post"
|
||||
|
||||
msgid "Re"
|
||||
msgstr "Re:"
|
||||
|
||||
msgid "Preview"
|
||||
msgstr "Предпросмотр"
|
||||
|
||||
msgid "Warnings"
|
||||
msgstr "Предупреждений:"
|
||||
|
||||
msgid "Reply"
|
||||
msgstr "Ответить"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Сейчас в этой теме пользователей: %s"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "гостей: %s"
|
|
@ -141,9 +141,9 @@
|
|||
</div>
|
||||
<div class="f-cell f-cstats">
|
||||
<ul>
|
||||
<li>{!! __('%s Reply', $topic['num_replies'], $topic['num_replies']) !!}</li>
|
||||
@if(null !== $topic['num_views'])
|
||||
<li>{!! __('%s View', $topic['num_views'], $topic['num_views'])!!}</li>
|
||||
<li>{!! __('%s Reply', $topic['num_replies'], $topic['replies']) !!}</li>
|
||||
@if($topic['views'])
|
||||
<li>{!! __('%s View', $topic['num_views'], $topic['views']) !!}</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
|
|
114
app/templates/topic.tpl
Normal file
114
app/templates/topic.tpl
Normal file
|
@ -0,0 +1,114 @@
|
|||
@section('crumbs')
|
||||
<ul class="f-crumbs">
|
||||
@foreach($crumbs as $cur)
|
||||
@if($cur[2])
|
||||
<li class="f-crumb"><a href="{!! $cur[0] !!}" class="active">{{ $cur[1] }}</a></li>
|
||||
@else
|
||||
<li class="f-crumb"><a href="{!! $cur[0] !!}">{{ $cur[1] }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
</ul>
|
||||
@endsection
|
||||
@section('linkpost')
|
||||
@if($newPost !== null)
|
||||
<div class="f-link-post">
|
||||
@if($newPost === false)
|
||||
__('Topic closed')
|
||||
@else
|
||||
<a class="f-btn" href="{!! $newPost !!}">{!! __('Post reply') !!}</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
||||
@section('pages')
|
||||
<nav class="f-pages">
|
||||
@foreach($pages as $cur)
|
||||
@if($cur[2])
|
||||
<span class="f-page active">{{ $cur[1] }}</span>
|
||||
@elseif($cur[1] === 'space')
|
||||
<span class="f-page f-pspacer">{!! __('Spacer') !!}</span>
|
||||
@elseif($cur[1] === 'prev')
|
||||
<a rel="prev" class="f-page f-pprev" href="{!! $cur[0] !!}">{!! __('Previous') !!}</a>
|
||||
@elseif($cur[1] === 'next')
|
||||
<a rel="next" class="f-page f-pnext" href="{!! $cur[0] !!}">{!! __('Next') !!}</a>
|
||||
@else
|
||||
<a class="f-page" href="{!! $cur[0] !!}">{{ $cur[1] }}</a>
|
||||
@endif
|
||||
@endforeach
|
||||
</nav>
|
||||
@endsection
|
||||
@extends('layouts/main')
|
||||
<div class="f-nav-links">
|
||||
@yield('crumbs')
|
||||
@if($newPost || $pages)
|
||||
<div class="f-links-b clearfix">
|
||||
@yield('pages')
|
||||
@yield('linkpost')
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<section class="f-main f-topic">
|
||||
<h2>{{ $topicName }}</h2>
|
||||
@foreach($posts as $post)
|
||||
<article id="p{!! $post['id'] !!}" class="f-post{!! $post['poster_gender'].$post['poster_online'] !!} clearfix">
|
||||
<div class="f-post-header clearfix">
|
||||
<h3>{{ $topicName }} - #{!! $post['post_number'] !!}</h3>
|
||||
<span class="left"><time datetime="{{ $post['posted_utc'] }}">{{ $post['posted'] }}</time></span>
|
||||
<span class="right"><a href="{!! $post['link'] !!}" rel="bookmark">#{!! $post['post_number'] !!}</a></span>
|
||||
</div>
|
||||
<div class="f-post-body clearfix">
|
||||
<address class="f-post-left clearfix">
|
||||
<ul class="f-user-info">
|
||||
@if($post['poster_link'])
|
||||
<li class="f-username"><a href="{!! $post['poster_link'] !!}">{{ $post['poster'] }}</a></li>
|
||||
@else
|
||||
<li class="f-username">{{ $post['poster'] }}</li>
|
||||
@endif
|
||||
@if($post['poster_avatar'])
|
||||
<li class="f-avatar">
|
||||
<img alt="{{ $post['poster'] }}" src="{!! $post['poster_avatar'] !!}">
|
||||
</li>
|
||||
@endif
|
||||
<li class="f-usertitle"><span>{{$post['poster_title']}}</span></li>
|
||||
@if($post['poster_posts'])
|
||||
<li class="f-postcount"><span>{!! __('%s post', $post['poster_num_posts'], $post['poster_posts']) !!}</span></li>
|
||||
@endif
|
||||
</ul>
|
||||
@if($post['poster_info_add'])
|
||||
<ul class="f-user-info-add">
|
||||
<li><span>{!! __('Registered:') !!} {{ $post['poster_registered'] }}</span></li>
|
||||
@if($post['poster_location'])
|
||||
<li><span>{!! __('From') !!} {{ $post['poster_location'] }}</span></li>
|
||||
@endif
|
||||
<li><span></span></li>
|
||||
</ul>
|
||||
@endif
|
||||
</address>
|
||||
|
||||
</div>
|
||||
<div class="f-post-footer clearfix">
|
||||
<div class="f-post-left">
|
||||
<span></span>
|
||||
</div>
|
||||
@if($post['controls'])
|
||||
<div class="f-post-right clearfix">
|
||||
<ul>
|
||||
@foreach($post['controls'] as $key => $control)
|
||||
<li class="f-post{!! $key !!}"><a class="f-btn" href="{!! $control[0] !!}">{!! __($control[1]) !!}</a></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</article>
|
||||
@endforeach
|
||||
</section>
|
||||
<div class="f-nav-links">
|
||||
@if($newPost || $pages)
|
||||
<div class="f-links-a clearfix">
|
||||
@yield('linkpost')
|
||||
@yield('pages')
|
||||
</div>
|
||||
@endif
|
||||
@yield('crumbs')
|
||||
</div>
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
$forkStart = empty($_SERVER['REQUEST_TIME_FLOAT']) ? microtime(true) : $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
$forkPublic = __DIR__;
|
||||
$forkPublicPrefix = '';
|
||||
|
||||
require __DIR__ . '/../app/bootstrap.php';
|
||||
|
|
|
@ -696,129 +696,6 @@ select {
|
|||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* Сообщение в теме */
|
||||
/********************/
|
||||
|
||||
.f-post {
|
||||
border-top: 0.0625rem solid #AA7939;
|
||||
margin-bottom: 0.625rem;
|
||||
position: relative;
|
||||
background-color: #FFFFFF;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.f-post-header > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-post-header {
|
||||
padding: 0.625rem;
|
||||
border-bottom: 0.0625rem solid #AA7939;
|
||||
background-color: #D3B58D;
|
||||
}
|
||||
|
||||
.f-post-left {
|
||||
padding: 0.625rem;
|
||||
background-color: #F8F4E3;
|
||||
}
|
||||
|
||||
.f-post-right {
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-post-footer li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
li + li .f-btn {
|
||||
margin-left: 0.1875rem;
|
||||
}
|
||||
|
||||
.f-user-info {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.f-user-info-custom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-username {
|
||||
font-size: 1.25rem;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.f-username a {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.f-avatar {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.f-avatar img {
|
||||
max-width: 4.6875rem;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.f-usertitle {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 50rem) {
|
||||
.f-post {
|
||||
background-color: #F8F4E3;
|
||||
}
|
||||
|
||||
.f-post-body, .f-post-footer {
|
||||
width: 100%;
|
||||
float: right;
|
||||
margin-right: -13rem;
|
||||
position: relative;
|
||||
border-left: 0.0625rem solid #AA7939;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.f-post-left {
|
||||
width: 11.75rem;
|
||||
margin-left: -13rem;
|
||||
float: left;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.f-post-right {
|
||||
padding-right: 13.625rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-left {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.f-user-info-custom {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.f-username, .f-avatar {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.f-avatar img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
} /* @media screen and (min-width: 50rem) */
|
||||
|
||||
/******************/
|
||||
/* Админка - меню */
|
||||
/******************/
|
||||
|
@ -1253,3 +1130,133 @@ li + li .f-btn {
|
|||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/* Страница темы */
|
||||
/*****************/
|
||||
.f-topic > h2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* Сообщение в теме */
|
||||
/********************/
|
||||
|
||||
.f-post {
|
||||
border-top: 0.0625rem solid #AA7939;
|
||||
margin-bottom: 0.625rem;
|
||||
position: relative;
|
||||
background-color: #FFFFFF;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.f-post-header > h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-post-header {
|
||||
padding: 0.625rem;
|
||||
border-bottom: 0.0625rem solid #AA7939;
|
||||
background-color: #D3B58D;
|
||||
}
|
||||
|
||||
.f-post-left {
|
||||
padding: 0.625rem;
|
||||
background-color: #F8F4E3;
|
||||
}
|
||||
|
||||
.f-post-right {
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-post-footer li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
li + li .f-btn {
|
||||
/* margin-left: 0.1875rem; */
|
||||
}
|
||||
|
||||
.f-user-info {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.f-user-info-add {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.f-username {
|
||||
font-size: 1.25rem;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.f-username a {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.f-avatar {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.f-avatar img {
|
||||
max-width: 4.6875rem;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.f-usertitle {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 50rem) {
|
||||
.f-post {
|
||||
background-color: #F8F4E3;
|
||||
}
|
||||
|
||||
.f-post-body, .f-post-footer {
|
||||
width: 100%;
|
||||
float: right;
|
||||
margin-right: -13rem;
|
||||
position: relative;
|
||||
border-left: 0.0625rem solid #AA7939;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.f-post-left {
|
||||
width: 11.75rem;
|
||||
margin-left: -13rem;
|
||||
float: left;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.f-post-right {
|
||||
padding-right: 13.625rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-left {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.f-user-info-add {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.f-username, .f-avatar {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.f-avatar img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
} /* @media screen and (min-width: 50rem) */
|
||||
|
|
Loading…
Add table
Reference in a new issue