2017-11-03
This commit is contained in:
parent
e3abb67d67
commit
37f80f6fb8
104 changed files with 3370 additions and 2670 deletions
|
@ -15,6 +15,7 @@ class Install
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -24,6 +25,7 @@ class Install
|
|||
|
||||
/**
|
||||
* Маршрутиризация
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function routing()
|
||||
|
@ -38,7 +40,7 @@ class Install
|
|||
. preg_replace('%:(80|443)$%', '', $_SERVER['HTTP_HOST'])
|
||||
. substr($uri, 0, (int) strrpos($uri, '/'));
|
||||
|
||||
$this->c->Lang->load('common', $this->c->config['o_default_lang']);
|
||||
$this->c->Lang->load('common', $this->c->config->o_default_lang);
|
||||
$this->c->user = new User(['id' => 2, 'group_id' => $this->c->GROUP_ADMIN], $this->c);
|
||||
|
||||
$r = $this->c->Router;
|
||||
|
@ -54,7 +56,7 @@ class Install
|
|||
$page = $this->c->$page->$action($route[2]);
|
||||
break;
|
||||
default:
|
||||
$page = $this->c->Redirect->setPage('Install')->setMessage('Redirect to install');
|
||||
$page = $this->c->Redirect->page('Install')->message('Redirect to install');
|
||||
break;
|
||||
}
|
||||
return $page;
|
||||
|
|
|
@ -14,6 +14,7 @@ class Primary
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -25,28 +26,27 @@ class Primary
|
|||
* Проверка на обслуживание
|
||||
* Проверка на обновление
|
||||
* Проверка на бан
|
||||
*
|
||||
* @return Page|null
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
if ($this->c->config['o_maintenance'] && ! $this->c->MAINTENANCE_OFF) {
|
||||
if (! in_array($this->c->UserCookie->id(), $this->c->admins)
|
||||
|| ! in_array($this->c->user->id, $this->c->admins)
|
||||
) {
|
||||
return $this->c->Maintenance;
|
||||
}
|
||||
if ($this->c->config->o_maintenance && ! $this->c->MAINTENANCE_OFF) {
|
||||
if (! in_array($this->c->Cookie->uId, $this->c->admins->list) //????
|
||||
|| ! in_array($this->c->user->id, $this->c->admins->list) //????
|
||||
) {
|
||||
return $this->c->Maintenance;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->c->config['i_fork_revision'])
|
||||
|| $this->c->config['i_fork_revision'] < $this->c->FORK_REVISION
|
||||
if ($this->c->config->i_fork_revision < $this->c->FORK_REVISION
|
||||
) {
|
||||
header('Location: db_update.php'); //????
|
||||
exit;
|
||||
}
|
||||
|
||||
$ban = $this->c->CheckBans->check();
|
||||
if (is_array($ban)) {
|
||||
return $this->c->Ban->ban($ban);
|
||||
if (! $this->c->user->isAdmin && $this->c->bans->check($this->c->user)) {
|
||||
return $this->c->Ban->ban($this->c->user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ class Routing
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -23,6 +24,7 @@ class Routing
|
|||
|
||||
/**
|
||||
* Маршрутиризация
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function routing()
|
||||
|
@ -44,7 +46,7 @@ class Routing
|
|||
$r->add('POST', '/login/{email}/{key}/{hash}', 'Auth:changePassPost');
|
||||
|
||||
// регистрация
|
||||
if ($config['o_regs_allow'] == '1') {
|
||||
if ($config->o_regs_allow == '1') {
|
||||
$r->add('GET', '/registration', 'Rules:confirmation', 'Register');
|
||||
$r->add('POST', '/registration/agree', 'Register:reg', 'RegisterForm');
|
||||
$r->add('GET', '/registration/activate/{id:\d+}/{key}/{hash}', 'Register:activate', 'RegActivate');
|
||||
|
@ -58,19 +60,19 @@ class Routing
|
|||
$r->add('GET', '/registration[/{tail:.*}]', 'Redirect:toIndex');
|
||||
}
|
||||
// просмотр разрешен
|
||||
if ($user->gReadBoard == '1') {
|
||||
if ($user->g_read_board == '1') {
|
||||
// главная
|
||||
$r->add('GET', '/', 'Index:view', 'Index');
|
||||
// правила
|
||||
if ($config['o_rules'] == '1' && (! $user->isGuest || $config['o_regs_allow'] == '1')) {
|
||||
if ($config->o_rules == '1' && (! $user->isGuest || $config->o_regs_allow == '1')) {
|
||||
$r->add('GET', '/rules', 'Rules:view', 'Rules');
|
||||
}
|
||||
// поиск
|
||||
if ($user->gSearch == '1') {
|
||||
if ($user->g_search == '1') {
|
||||
$r->add('GET', '/search', 'Search:view', 'Search');
|
||||
}
|
||||
// юзеры
|
||||
if ($user->gViewUsers == '1') {
|
||||
if ($user->g_view_users == '1') {
|
||||
// список пользователей
|
||||
$r->add('GET', '/userlist[/{page:[1-9]\d*}]', 'Userlist:view', 'Userlist');
|
||||
// юзеры
|
||||
|
@ -127,8 +129,8 @@ class Routing
|
|||
break;
|
||||
case $r::NOT_FOUND:
|
||||
// ... 404 Not Found
|
||||
if ($user->gReadBoard != '1' && $user->isGuest) {
|
||||
$page = $this->c->Redirect->setPage('Login');
|
||||
if ($user->g_read_board != '1' && $user->isGuest) {
|
||||
$page = $this->c->Redirect->page('Login');
|
||||
} else {
|
||||
$page = $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
abstract class AbstractModel
|
||||
{
|
||||
/**
|
||||
* Данные модели
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
abstract protected function beforeConstruct(array $data);
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$data = $this->beforeConstruct($data);
|
||||
foreach ($data as $key => $val) {
|
||||
if (is_string($key)) {
|
||||
$this->data[$this->camelCase($key)] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет наличие свойства
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return is_string($key) && isset($this->data[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет свойство
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
if (is_string($key)) {
|
||||
unset($this->data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значение для свойства
|
||||
* При $key = __attrs ожидаем массив в $val
|
||||
* @param mixed $key
|
||||
* @param mixed $vak
|
||||
*/
|
||||
public function __set($key, $val)
|
||||
{
|
||||
if ('__attrs' === $key) {
|
||||
if (is_array($val)) {
|
||||
foreach ($val as $x => $y) {
|
||||
$x = $this->camelCase($x);
|
||||
$this->$x = $y;
|
||||
}
|
||||
}
|
||||
} elseif (is_string($key)) {
|
||||
$method = 'set' . ucfirst($key);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($val);
|
||||
} else {
|
||||
$this->data[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение свойства
|
||||
* При $key = __attrs возвращает все свойства
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
if ('__attrs' === $key) {
|
||||
$data = [];
|
||||
foreach ($this->data as $x => $y) {
|
||||
$data[$this->underScore($x)] = $y; //????
|
||||
}
|
||||
return $data;
|
||||
} elseif (is_string($key)) {
|
||||
$method = 'get' . ucfirst($key);
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method();
|
||||
} else {
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует строку в camelCase
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
protected function camelCase($str)
|
||||
{
|
||||
return lcfirst(str_replace('_', '', ucwords($str, '_')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует строку в under_score
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
protected function underScore($str)
|
||||
{
|
||||
return preg_replace('%([A-Z])%', function($match) {
|
||||
return '_' . strtolower($match[1]);
|
||||
}, $str);
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@ class FileCache implements ProviderCacheInterface
|
|||
*
|
||||
* @param string $dir
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \RuntimeException
|
||||
* @throws InvalidArgumentException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct($dir)
|
||||
{
|
||||
|
@ -63,7 +63,8 @@ class FileCache implements ProviderCacheInterface
|
|||
* @param mixed $value
|
||||
* @param int $ttl
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set($key, $value, $ttl = null)
|
||||
|
@ -84,7 +85,8 @@ class FileCache implements ProviderCacheInterface
|
|||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($key)
|
||||
|
@ -141,7 +143,8 @@ class FileCache implements ProviderCacheInterface
|
|||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function file($key)
|
||||
|
|
|
@ -18,6 +18,7 @@ class Container
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array config
|
||||
*/
|
||||
public function __construct(array $config = null)
|
||||
|
@ -37,6 +38,7 @@ class Container
|
|||
|
||||
/**
|
||||
* Adding config
|
||||
*
|
||||
* @param array config
|
||||
*/
|
||||
public function config(array $config)
|
||||
|
@ -53,9 +55,12 @@ class Container
|
|||
|
||||
/**
|
||||
* Gets a service or parameter.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __get($id)
|
||||
{
|
||||
|
@ -79,7 +84,7 @@ class Container
|
|||
$toShare = false;
|
||||
$config = (array) $this->multiple[$id];
|
||||
} else {
|
||||
throw new InvalidArgumentException('Wrong property name '.$id);
|
||||
throw new InvalidArgumentException('Wrong property name: ' . $id);
|
||||
}
|
||||
// N.B. "class" is just the first element, regardless of its key
|
||||
$class = array_shift($config);
|
||||
|
@ -107,6 +112,7 @@ class Container
|
|||
/**
|
||||
* Sets a service or parameter.
|
||||
* Provides a fluent interface.
|
||||
*
|
||||
* @param string $id
|
||||
* @param mixed $service
|
||||
*/
|
||||
|
@ -121,8 +127,10 @@ class Container
|
|||
|
||||
/**
|
||||
* Gets data from array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array $tree
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fromArray(array $array, array $tree)
|
||||
|
@ -145,21 +153,23 @@ class Container
|
|||
* @param string $name The parameter name
|
||||
* @param mixed $value The parameter value
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return ContainerInterface Self reference
|
||||
*/
|
||||
public function setParameter($name, $value)
|
||||
{
|
||||
$segments = explode('.', $name);
|
||||
$n = count($segments);
|
||||
$ptr =& $this->config;
|
||||
$ptr = &$this->config;
|
||||
foreach ($segments as $s) {
|
||||
if (--$n) {
|
||||
if (!array_key_exists($s, $ptr)) {
|
||||
if (! array_key_exists($s, $ptr)) {
|
||||
$ptr[$s] = [];
|
||||
} elseif (!is_array($ptr[$s])) {
|
||||
throw new \InvalidArgumentException("Scalar \"{$s}\" in the path \"{$name}\"");
|
||||
} elseif (! is_array($ptr[$s])) {
|
||||
throw new InvalidArgumentException("Scalar '{$s}' in the path '{$name}'");
|
||||
}
|
||||
$ptr =& $ptr[$s];
|
||||
$ptr = &$ptr[$s];
|
||||
} else {
|
||||
$ptr[$s] = $value;
|
||||
}
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
use ForkBB\Core\Secury;
|
||||
|
||||
class Cookie
|
||||
{
|
||||
/**
|
||||
* @var Secury
|
||||
*/
|
||||
protected $secury;
|
||||
|
||||
/**
|
||||
* Префикс для наименований
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Домен
|
||||
* @var string
|
||||
*/
|
||||
protected $domain;
|
||||
|
||||
/**
|
||||
* Путь
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Флаг передачи кук по защищенному соединению
|
||||
* @var bool
|
||||
*/
|
||||
protected $secure;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Secury $secury
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(Secury $secury, array $options)
|
||||
{
|
||||
$this->secury = $secury;
|
||||
|
||||
$options += [
|
||||
'prefix' => '',
|
||||
'domain' => '',
|
||||
'path' => '',
|
||||
'secure' => false,
|
||||
];
|
||||
|
||||
$this->prefix = (string) $options['prefix'];
|
||||
$this->domain = (string) $options['domain'];
|
||||
$this->path = (string) $options['path'];
|
||||
$this->secure = (bool) $options['secure'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает куку
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param int $expire
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @param bool $secure
|
||||
* @param bool $httponly
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set($name, $value, $expire = 0, $path = null, $domain = null, $secure = false, $httponly = true)
|
||||
{
|
||||
$name = $this->prefix . $name;
|
||||
$path = isset($path) ? $path : $this->path;
|
||||
$domain = isset($domain) ? $domain : $this->domain;
|
||||
$secure = $this->secure || (bool) $secure;
|
||||
$result = setcookie($name, $value, $expire, $path, $domain, $secure, (bool) $httponly);
|
||||
if ($result) {
|
||||
$_COOKIE[$name] = $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает значение куки
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
$name = $this->prefix . $name;
|
||||
return isset($_COOKIE[$name]) ? $this->secury->replInvalidChars($_COOKIE[$name]) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет куку
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($name, $path = null, $domain = null)
|
||||
{
|
||||
$result = $this->set($name, '', 1, $path, $domain);
|
||||
if ($result) {
|
||||
unset($_COOKIE[$this->prefix . $name]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ class Csrf
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Secury $secury
|
||||
* @param User $user
|
||||
*/
|
||||
|
@ -29,9 +30,11 @@ class Csrf
|
|||
|
||||
/**
|
||||
* Возвращает csrf токен
|
||||
*
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
* @param string|int $time
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function create($marker, array $args = [], $time = null)
|
||||
|
@ -48,9 +51,11 @@ class Csrf
|
|||
|
||||
/**
|
||||
* Проверка токена
|
||||
*
|
||||
* @param mixed $token
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($token, $marker, array $args = [])
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
use ForkBB\Core\DBStatement;
|
||||
use PDO;
|
||||
use PDOStatement;
|
||||
use PDOException;
|
||||
use ForkBB\Core\DBStatement;
|
||||
|
||||
class DB extends PDO
|
||||
{
|
||||
|
|
|
@ -34,6 +34,25 @@ class Mysql
|
|||
'%^SERIAL$%i' => 'INT(10) UNSIGNED AUTO_INCREMENT',
|
||||
];
|
||||
|
||||
/**
|
||||
* Подстановка типов полей для карты БД
|
||||
* @var array
|
||||
*/
|
||||
protected $types = [
|
||||
'bool' => 'b',
|
||||
'boolean' => 'b',
|
||||
'tinyint' => 'i',
|
||||
'smallint' => 'i',
|
||||
'mediumint' => 'i',
|
||||
'int' => 'i',
|
||||
'integer' => 'i',
|
||||
'bigint' => 'i',
|
||||
'decimal' => 'i',
|
||||
'dec' => 'i',
|
||||
'float' => 'i',
|
||||
'double' => 'i',
|
||||
];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
|
@ -524,4 +543,26 @@ class Mysql
|
|||
'server info' => $this->db->getAttribute(\PDO::ATTR_SERVER_INFO),
|
||||
] + $other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует карту базы данных
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$stmt = $this->db->query('SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE ?s', ["{$this->dbPrefix}%"]);
|
||||
$result = [];
|
||||
$table = null;
|
||||
while ($row = $stmt->fetch()) {
|
||||
if ($table !== $row['TABLE_NAME']) {
|
||||
$table = $row['TABLE_NAME'];
|
||||
$tableNoPref = substr($table, strlen($this->dbPrefix));
|
||||
$result[$tableNoPref] = [];
|
||||
}
|
||||
$type = strtolower($row['DATA_TYPE']);
|
||||
$result[$tableNoPref][$row['COLUMN_NAME']] = isset($this->types[$type]) ? $this->types[$type] : 's';
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ class Func
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
|
@ -61,10 +63,13 @@ class Func
|
|||
}
|
||||
|
||||
/**
|
||||
* Пагинация
|
||||
*
|
||||
* @param int $all
|
||||
* @param int $cur
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function paginate($all, $cur, $marker, array $args = [])
|
||||
|
|
|
@ -27,6 +27,7 @@ class Lang
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -37,8 +38,10 @@ class Lang
|
|||
|
||||
/**
|
||||
* Ищет сообщение в загруженных переводах
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $lang
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public function get($message, $lang = null)
|
||||
|
@ -58,6 +61,7 @@ class Lang
|
|||
|
||||
/**
|
||||
* Загрузка языкового файла
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $lang
|
||||
* @param string $path
|
||||
|
@ -95,9 +99,12 @@ class Lang
|
|||
|
||||
/**
|
||||
* Получение массива перевода из строки (.po файла)
|
||||
*
|
||||
* @param string $str
|
||||
* @return array
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function arrayFromStr($str)
|
||||
{
|
||||
|
@ -242,7 +249,9 @@ class Lang
|
|||
/**
|
||||
* Получение оригинальной строки с удалением кавычек
|
||||
* и преобразованием спецсимволов
|
||||
*
|
||||
* @param string $line
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function originalLine($line)
|
||||
|
@ -256,5 +265,4 @@ class Lang
|
|||
$line
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class Mail
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param mixed $host
|
||||
* @param mixed $user
|
||||
* @param mixed $pass
|
||||
|
@ -81,9 +82,11 @@ class Mail
|
|||
|
||||
/**
|
||||
* Валидация email
|
||||
*
|
||||
* @param mixed $email
|
||||
* @param bool $strict
|
||||
* @param bool $idna
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function valid($email, $strict = false, $idna = false)
|
||||
|
@ -113,6 +116,7 @@ class Mail
|
|||
|
||||
/**
|
||||
* Сброс
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function reset()
|
||||
|
@ -125,7 +129,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает тему письма
|
||||
*
|
||||
* @param string $subject
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
|
@ -136,8 +142,10 @@ class Mail
|
|||
|
||||
/**
|
||||
* Добавляет заголовок To
|
||||
*
|
||||
* @param string|array $email
|
||||
* @param string $name
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function addTo($email, $name = null)
|
||||
|
@ -157,8 +165,10 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает заголовок To
|
||||
*
|
||||
* @param string|array $email
|
||||
* @param string $name
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setTo($email, $name = null)
|
||||
|
@ -169,8 +179,10 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает заголовок From
|
||||
*
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setFrom($email, $name = null)
|
||||
|
@ -184,8 +196,10 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает заголовок Reply-To
|
||||
*
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setReplyTo($email, $name = null)
|
||||
|
@ -199,8 +213,10 @@ class Mail
|
|||
|
||||
/**
|
||||
* Форматирование адреса
|
||||
*
|
||||
* @param string|array $email
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatAddress($email, $name = null)
|
||||
|
@ -215,7 +231,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Кодирование заголовка/имени
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeText($str)
|
||||
|
@ -229,7 +247,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Фильтрация имени
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function filterName($name)
|
||||
|
@ -239,7 +259,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Установка папки для поиска шаблонов писем
|
||||
*
|
||||
* @param string $folder
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setFolder($folder)
|
||||
|
@ -250,7 +272,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Установка языка для поиска шаблонов писем
|
||||
*
|
||||
* @param string $language
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
|
@ -261,9 +285,12 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает сообщение по шаблону
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param array $data
|
||||
*
|
||||
* @throws MailException
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setTpl($tpl, array $data)
|
||||
|
@ -286,7 +313,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Задает сообщение
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return Mail
|
||||
*/
|
||||
public function setMessage($message)
|
||||
|
@ -300,7 +329,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Отправляет письмо
|
||||
*
|
||||
* @throws MailException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send()
|
||||
|
@ -335,6 +366,7 @@ class Mail
|
|||
|
||||
/**
|
||||
* Отправка письма через функцию mail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function mail()
|
||||
|
@ -349,7 +381,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Переводит заголовки из массива в строку
|
||||
*
|
||||
* @param array $headers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function strHeaders(array $headers)
|
||||
|
@ -363,7 +397,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Отправка письма через smtp
|
||||
*
|
||||
* @throws SmtpException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function smtp()
|
||||
|
@ -423,9 +459,12 @@ class Mail
|
|||
* Отправляет данные на сервер
|
||||
* Проверяет ответ
|
||||
* Возвращает код ответа
|
||||
*
|
||||
* @param string $data
|
||||
* @param mixed $code
|
||||
*
|
||||
* @throws SmtpException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function smtpData($data, $code)
|
||||
|
@ -454,7 +493,9 @@ class Mail
|
|||
|
||||
/**
|
||||
* Выделяет email из заголовка
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEmailFrom($str)
|
||||
|
@ -469,6 +510,7 @@ class Mail
|
|||
|
||||
/**
|
||||
* Возвращает имя сервера или его ip
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function hostname()
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
class Request
|
||||
{
|
||||
/**
|
||||
* @var Secury
|
||||
*/
|
||||
protected $secury;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Secury $secury
|
||||
*/
|
||||
public function __construct($secury)
|
||||
{
|
||||
$this->secury = $secury;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRequest($key)
|
||||
{
|
||||
return $this->isPost($key) || $this->isGet($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function request($key, $default = null)
|
||||
{
|
||||
if (($result = $this->post($key)) === null
|
||||
&& ($result = $this->get($key)) === null
|
||||
) {
|
||||
return $default;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestStr($key, $default = null)
|
||||
{
|
||||
if (($result = $this->postStr($key)) === null
|
||||
&& ($result = $this->getStr($key)) === null
|
||||
) {
|
||||
return $default;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestInt($key, $default = null)
|
||||
{
|
||||
if (($result = $this->postInt($key)) === null
|
||||
&& ($result = $this->getInt($key)) === null
|
||||
) {
|
||||
return $default;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function requestBool($key, $default = null)
|
||||
{
|
||||
if (($result = $this->postBool($key)) === null
|
||||
&& ($result = $this->getBool($key)) === null
|
||||
) {
|
||||
return $default;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPost($key)
|
||||
{
|
||||
return isset($_POST[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function post($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key])) {
|
||||
return $this->secury->replInvalidChars($_POST[$key]);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function postStr($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key]) && is_string($_POST[$key])) {
|
||||
return (string) $this->secury->replInvalidChars($_POST[$key]);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function postInt($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key]) && is_numeric($_POST[$key]) && is_int(0 + $_POST[$key])) {
|
||||
return (int) $_POST[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function postBool($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key]) && is_string($_POST[$key])) {
|
||||
return (bool) $_POST[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function postKey($key, $default = null)
|
||||
{
|
||||
if (isset($_POST[$key]) && is_array($_POST[$key])) {
|
||||
$k = key($_POST[$key]);
|
||||
if (null !== $k) {
|
||||
return is_int($k) ? (int) $k : (string) $this->secury->replInvalidChars($k);
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGet($key)
|
||||
{
|
||||
return isset($_GET[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (isset($_GET[$key])) {
|
||||
return $this->secury->replInvalidChars($_GET[$key]);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStr($key, $default = null)
|
||||
{
|
||||
if (isset($_GET[$key]) && is_string($_GET[$key])) {
|
||||
return (string) $this->secury->replInvalidChars($_GET[$key]);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInt($key, $default = null)
|
||||
{
|
||||
if (isset($_GET[$key]) && is_numeric($_GET[$key]) && is_int(0 + $_GET[$key])) {
|
||||
return (int) $_GET[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBool($key, $default = null)
|
||||
{
|
||||
if (isset($_GET[$key]) && is_string($_GET[$key])) {
|
||||
return (bool) $_GET[$key];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ class Router
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param string $base
|
||||
*/
|
||||
public function __construct($base)
|
||||
|
@ -71,9 +72,11 @@ class Router
|
|||
|
||||
/**
|
||||
* Проверка url на принадлежность форуму
|
||||
*
|
||||
* @param mixed $url
|
||||
* @param string $defMarker
|
||||
* @param array $defArgs
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function validate($url, $defMarker, array $defArgs = [])
|
||||
|
@ -91,8 +94,10 @@ class Router
|
|||
|
||||
/**
|
||||
* Возвращает ссылку на основании маркера
|
||||
*
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function link($marker = null, array $args = [])
|
||||
|
@ -127,8 +132,10 @@ class Router
|
|||
|
||||
/**
|
||||
* Метод определяет маршрут
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function route($method, $uri)
|
||||
|
@ -195,6 +202,7 @@ class Router
|
|||
|
||||
/**
|
||||
* Метод добавдяет маршрут
|
||||
*
|
||||
* @param string|array $method
|
||||
* @param string $route
|
||||
* @param string $handler
|
||||
|
@ -244,7 +252,9 @@ class Router
|
|||
|
||||
/**
|
||||
* Метод разбирает динамический маршрут
|
||||
*
|
||||
* @param string $route
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
protected function parse($route)
|
||||
|
|
|
@ -16,9 +16,11 @@ class Secury
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array $hmac
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \UnexpectedValueException
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public function __construct(array $hmac)
|
||||
{
|
||||
|
@ -33,7 +35,9 @@ class Secury
|
|||
|
||||
/**
|
||||
* Обертка для hash_hmac
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hash($data)
|
||||
|
@ -43,10 +47,13 @@ class Secury
|
|||
|
||||
/**
|
||||
* Обертка для hash_hmac
|
||||
*
|
||||
* @param string $data
|
||||
* @param string $key
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function hmac($data, $key)
|
||||
{
|
||||
|
@ -58,9 +65,12 @@ class Secury
|
|||
|
||||
/**
|
||||
* Возвращает случайный набор байтов заданной длины
|
||||
*
|
||||
* @param int $len
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function randomKey($len)
|
||||
{
|
||||
|
@ -85,7 +95,9 @@ class Secury
|
|||
|
||||
/**
|
||||
* Возвращает случайную строку заданной длины состоящую из символов 0-9 и a-f
|
||||
*
|
||||
* @param int $len
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function randomHash($len)
|
||||
|
@ -96,7 +108,9 @@ class Secury
|
|||
/**
|
||||
* Возвращает случайную строку заданной длины состоящую из цифр, латиницы,
|
||||
* знака минус и символа подчеркивания
|
||||
*
|
||||
* @param int $len
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function randomPass($len)
|
||||
|
@ -112,7 +126,9 @@ class Secury
|
|||
|
||||
/**
|
||||
* Replacing invalid UTF-8 characters and remove control characters
|
||||
*
|
||||
* @param string|array $data
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public function replInvalidChars($data)
|
||||
|
|
|
@ -75,6 +75,7 @@ class Validator
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -104,8 +105,10 @@ class Validator
|
|||
|
||||
/**
|
||||
* Добавление новых валидаторов
|
||||
*
|
||||
* @param array $validators
|
||||
* @param Validator
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
public function addValidators(array $validators)
|
||||
{
|
||||
|
@ -115,9 +118,12 @@ class Validator
|
|||
|
||||
/**
|
||||
* Установка правил проверки
|
||||
*
|
||||
* @param array $list
|
||||
* @return Validator
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
public function setRules(array $list)
|
||||
{
|
||||
|
@ -149,7 +155,9 @@ class Validator
|
|||
|
||||
/**
|
||||
* Установка дополнительных аргументов для конкретных "имя поля"."имя правила".
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
|
@ -160,7 +168,9 @@ class Validator
|
|||
|
||||
/**
|
||||
* Установка сообщений для конкретных "имя поля"."имя правила".
|
||||
*
|
||||
* @param array $messages
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
public function setMessages(array $messages)
|
||||
|
@ -171,7 +181,9 @@ class Validator
|
|||
|
||||
/**
|
||||
* Установка псевдонимов имен полей для сообщений об ошибках
|
||||
*
|
||||
* @param array $aliases
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
public function setAliases(array $aliases)
|
||||
|
@ -183,9 +195,12 @@ class Validator
|
|||
/**
|
||||
* Проверка данных
|
||||
* Удачная проверка возвращает true
|
||||
*
|
||||
* @param array $raw
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return bool
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function validation(array $raw)
|
||||
{
|
||||
|
@ -204,7 +219,9 @@ class Validator
|
|||
|
||||
/**
|
||||
* Проверяет наличие поля
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($field)
|
||||
|
@ -215,9 +232,12 @@ class Validator
|
|||
/**
|
||||
* Проверяет поле согласно заданным правилам
|
||||
* Возвращает значение запрашиваемого поля
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __get($field)
|
||||
{
|
||||
|
@ -259,8 +279,10 @@ class Validator
|
|||
|
||||
/**
|
||||
* Получение дополнительных аргументов
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $field
|
||||
* @param string $rule
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getArguments($field, $rule)
|
||||
|
@ -276,6 +298,7 @@ class Validator
|
|||
|
||||
/**
|
||||
* Обработка ошибки
|
||||
*
|
||||
* @param mixed $error
|
||||
* @param string $field
|
||||
* @param string $rule
|
||||
|
@ -302,7 +325,9 @@ class Validator
|
|||
|
||||
/**
|
||||
* Возвращает статус проверки поля
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getStatus($field)
|
||||
|
@ -316,8 +341,10 @@ class Validator
|
|||
/**
|
||||
* Возвращает проверенные данные
|
||||
* Поля с ошибками содержат значения по умолчанию или значения с ошибками
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return array
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
|
@ -329,6 +356,7 @@ class Validator
|
|||
|
||||
/**
|
||||
* Возращает массив ошибок
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace ForkBB\Core;
|
||||
|
||||
use R2\Templating\Dirk;
|
||||
use ForkBB\Models\Pages\Page;
|
||||
use ForkBB\Models\Page;
|
||||
use RuntimeException;
|
||||
|
||||
class View extends Dirk
|
||||
|
@ -24,7 +24,9 @@ class View extends Dirk
|
|||
|
||||
/**
|
||||
* Трансформация скомпилированного шаблона
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compileTransformations($value)
|
||||
|
@ -41,23 +43,38 @@ class View extends Dirk
|
|||
);
|
||||
}
|
||||
|
||||
public function rendering(Page $page)
|
||||
/**
|
||||
* Return result of templating
|
||||
*
|
||||
* @param Page $p
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function rendering(Page $p)
|
||||
{
|
||||
if (! $page->isReady()) {
|
||||
throw new RuntimeException('The page model does not contain data ready');
|
||||
}
|
||||
|
||||
$headers = $page->httpHeaders();
|
||||
foreach ($headers as $header) {
|
||||
foreach ($p->httpHeaders as $header) {
|
||||
header($header);
|
||||
}
|
||||
|
||||
$tpl = $page->getNameTpl();
|
||||
// переадресация
|
||||
if (null === $tpl) {
|
||||
if (null === $p->nameTpl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->fetch($tpl, $page->getData());
|
||||
$p->prepare();
|
||||
|
||||
$this->templates[] = $p->nameTpl;
|
||||
while ($_name = array_shift($this->templates)) {
|
||||
$this->beginBlock('content');
|
||||
foreach ($this->composers as $_cname => $_cdata) {
|
||||
if (preg_match($_cname, $_name)) {
|
||||
foreach ($_cdata as $_citem) {
|
||||
extract((is_callable($_citem) ? $_citem($this) : $_citem) ?: []);
|
||||
}
|
||||
}
|
||||
}
|
||||
require($this->prepare($_name));
|
||||
$this->endBlock(true);
|
||||
}
|
||||
return $this->block('content');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,20 +86,28 @@ class CacheGenerator
|
|||
return $this->c->DB->query('SELECT text, image FROM ::smilies ORDER BY disp_position')->fetchAll(\PDO::FETCH_KEY_PAIR); //???? text уникальное?
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив карты базы данных
|
||||
*/
|
||||
public function dbMap()
|
||||
{
|
||||
return $this->c->DB->getMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив с описанием форумов для текущего пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function forums(User $user)
|
||||
{
|
||||
$stmt = $this->c->DB->query('SELECT g_read_board FROM ::groups WHERE g_id=?i:id', [':id' => $user->gId]);
|
||||
$stmt = $this->c->DB->query('SELECT g_read_board FROM ::groups WHERE g_id=?i:id', [':id' => $user->group_id]);
|
||||
$read = $stmt->fetchColumn();
|
||||
$stmt->closeCursor();
|
||||
|
||||
$tree = $desc = $asc = [];
|
||||
|
||||
if ($read) {
|
||||
$stmt = $this->c->DB->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.redirect_url, f.parent_forum_id, f.disp_position, fp.post_topics, fp.post_replies FROM ::categories AS c INNER JOIN ::forums AS f ON c.id=f.cat_id LEFT JOIN ::forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=?i:gid) WHERE fp.read_forum IS NULL OR fp.read_forum=1 ORDER BY c.disp_position, c.id, f.disp_position', [':gid' => $user->groupId]);
|
||||
$stmt = $this->c->DB->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.redirect_url, f.parent_forum_id, f.disp_position, fp.post_topics, fp.post_replies FROM ::categories AS c INNER JOIN ::forums AS f ON c.id=f.cat_id LEFT JOIN ::forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=?i:gid) WHERE fp.read_forum IS NULL OR fp.read_forum=1 ORDER BY c.disp_position, c.id, f.disp_position', [':gid' => $user->group_id]);
|
||||
while ($f = $stmt->fetch()) {
|
||||
$tree[$f['parent_forum_id']][$f['fid']] = $f;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class CacheLoader
|
|||
public function loadForums()
|
||||
{
|
||||
$mark = $this->cache->get('forums_mark');
|
||||
$key = 'forums_' . $this->c->user->gId;
|
||||
$key = 'forums_' . $this->c->user->group_id;
|
||||
|
||||
if (empty($mark)) {
|
||||
$this->cache->set('forums_mark', time());
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Actions;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
|
||||
class CheckBans
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Содержит массив с описание бана для проверяемого юзера
|
||||
*/
|
||||
protected $ban;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив с описанием бана или null
|
||||
* @return null|array
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$user = $this->c->user;
|
||||
|
||||
if ($user->isAdmin) {
|
||||
return null;
|
||||
} elseif ($user->isGuest) {
|
||||
$banned = $this->isBanned(null, null, $user->ip);
|
||||
} else {
|
||||
$banned = $this->isBanned($user->username, $user->email, $user->ip);
|
||||
}
|
||||
|
||||
if ($banned) {
|
||||
$this->c->Online->delete($user); //???? а зачем это надо?
|
||||
return $this->ban;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет наличие бана на основании имени юзера, email и(или) ip
|
||||
* Удаляет просроченные баны
|
||||
* @param string $username
|
||||
* @param string $email
|
||||
* @param string $userIp
|
||||
* @return int
|
||||
*/
|
||||
public function isBanned($username = null, $email = null, $userIp = null)
|
||||
{
|
||||
$bans = $this->c->bans;
|
||||
if (empty($bans)) {
|
||||
return 0;
|
||||
}
|
||||
if (isset($username)) {
|
||||
$username = mb_strtolower($username, 'UTF-8');
|
||||
}
|
||||
if (isset($userIp)) {
|
||||
// Add a dot or a colon (depending on IPv4/IPv6) at the end of the IP address to prevent banned address
|
||||
// 192.168.0.5 from matching e.g. 192.168.0.50
|
||||
$add = strpos($userIp, '.') !== false ? '.' : ':';
|
||||
$userIp .= $add;
|
||||
}
|
||||
|
||||
$banned = 0;
|
||||
$remove = [];
|
||||
$now = time();
|
||||
|
||||
foreach ($bans as $cur) {
|
||||
if ($cur['expire'] != '' && $cur['expire'] < $now) {
|
||||
$remove[] = $cur['id'];
|
||||
continue;
|
||||
} elseif (isset($username) && $cur['username'] != '' && $username == mb_strtolower($cur['username'])) {
|
||||
$this->ban = $cur;
|
||||
$banned = 1;
|
||||
break;
|
||||
} elseif (isset($email) && $cur['email'] != '' && $email == $cur['email']) {
|
||||
$this->ban = $cur;
|
||||
$banned = 2;
|
||||
break;
|
||||
} elseif (isset($userIp) && $cur['ip'] != '') {
|
||||
foreach (explode(' ', $cur['ip']) as $ip) {
|
||||
$ip .= $add;
|
||||
if (substr($userIp, 0, strlen($ip)) == $ip) {
|
||||
$this->ban = $cur;
|
||||
$banned = 3;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! empty($remove))
|
||||
{
|
||||
$this->c->DB->exec('DELETE FROM ::bans WHERE id IN (?ai:remove)', [':remove' => $remove]);
|
||||
$this->c->{'bans update'};
|
||||
}
|
||||
return $banned;
|
||||
}
|
||||
}
|
23
app/Models/AdminList.php
Normal file
23
app/Models/AdminList.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class AdminList extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список id админов из кеша/БД
|
||||
*
|
||||
* @return AdminList
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('admins')) {
|
||||
$this->list = $this->c->Cache->get('admins');
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
22
app/Models/AdminList/Load.php
Normal file
22
app/Models/AdminList/Load.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\AdminList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return AdminList
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$list = $this->c->DB->query('SELECT id FROM ::users WHERE group_id=?i', [$this->c->GROUP_ADMIN])->fetchAll(\PDO::FETCH_COLUMN);
|
||||
$this->model->list = $list;
|
||||
$this->c->Cache->set('admins', $list);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
46
app/Models/BanList.php
Normal file
46
app/Models/BanList.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class BanList extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список банов из кеша/БД
|
||||
*
|
||||
* @return BanList
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('banlist')) {
|
||||
$list = $this->c->Cache->get('banlist');
|
||||
$this->otherList = $list['otherList'];
|
||||
$this->userList = $list['userList'];
|
||||
$this->ipList = $list['ipList'];
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Фильтрует значение
|
||||
*
|
||||
* @param mixed $val
|
||||
* @param bool $toLower
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function trimToNull($val, $toLower = false)
|
||||
{
|
||||
$val = trim($val);
|
||||
if ($val == '') {
|
||||
return null;
|
||||
} elseif ($toLower) {
|
||||
return mb_strtolower($val, 'UTF-8');
|
||||
} else {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
}
|
67
app/Models/BanList/Check.php
Normal file
67
app/Models/BanList/Check.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\BanList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
use ForkBB\Models\User;
|
||||
|
||||
class Check extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Проверяет наличие бана (для текущего пользователя) на основании имени пользователя/ip
|
||||
* Удаляет просроченные баны
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check(User $user)
|
||||
{
|
||||
// админ
|
||||
if ($user->isAdmin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// удаление просроченных банов
|
||||
$now = time();
|
||||
$ids = [];
|
||||
foreach ($this->model->otherList as $id => $row) {
|
||||
if (null !== $row['expire'] && $row['expire'] < $now) {
|
||||
$ids[] = $id;
|
||||
}
|
||||
}
|
||||
if (! empty($ids)) {
|
||||
$this->model->delete($ids);
|
||||
}
|
||||
|
||||
// проверка гостя
|
||||
if ($user->isGuest) {
|
||||
$ip = $this->model->trimToNull($user->ip);
|
||||
if (null === $ip) {
|
||||
return false; //????
|
||||
}
|
||||
$add = strpos($ip, ':') === false ? '.' : ':'; //????
|
||||
$ip .= $add;
|
||||
foreach ($this->model->ipList as $addr => $id) {
|
||||
$addr .= $add;
|
||||
if (substr($ip, 0, strlen($addr)) == $addr) {
|
||||
if (isset($this->model->otherList[$id])) {
|
||||
$user->__banInfo = $this->model->otherList[$id];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// проверка пользователя
|
||||
} else {
|
||||
$name = $this->model->trimToNull($user->username, true);
|
||||
if (isset($this->model->userList[$name])) {
|
||||
$id = $this->model->userList[$name];
|
||||
if (isset($this->model->otherList[$id])) {
|
||||
$user->__banInfo = $this->model->otherList[$id];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
25
app/Models/BanList/Delete.php
Normal file
25
app/Models/BanList/Delete.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\BanList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Delete extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Удаляет из банов записи по списку номеров
|
||||
* Обновляет кеш
|
||||
*
|
||||
* @param array $ids
|
||||
*
|
||||
* @return BanList
|
||||
*/
|
||||
public function delete(array $ids)
|
||||
{
|
||||
if (! empty($ids)) {
|
||||
$this->c->DB->exec('DELETE FROM ::bans WHERE id IN (?ai:ids)', [':ids' => $ids]);
|
||||
$this->model->load();
|
||||
}
|
||||
return $this->model;
|
||||
}
|
||||
}
|
35
app/Models/BanList/IsBanned.php
Normal file
35
app/Models/BanList/IsBanned.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\BanList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
use ForkBB\Models\User;
|
||||
|
||||
class IsBanned extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Проверяет наличие бана на основании имени пользователя и(или) email
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function isBanned(User $user)
|
||||
{
|
||||
$name = $this->trimToNull($this->model->username, true);
|
||||
if (null !== $name && isset($this->model->userList[$name])) {
|
||||
return 1;
|
||||
}
|
||||
$email = $this->trimToNull($this->model->email);
|
||||
if (null !== $email) {
|
||||
foreach ($this->model->otherList as $row) {
|
||||
if (null === $row['email']) {
|
||||
continue;
|
||||
} elseif ($email == $row['email']) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
60
app/Models/BanList/Load.php
Normal file
60
app/Models/BanList/Load.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\BanList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Загружает список банов из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return BanList
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$userList = [];
|
||||
$ipList = [];
|
||||
$otherList = [];
|
||||
$stmt = $this->c->DB->query('SELECT id, username, ip, email, message, expire FROM ::bans');
|
||||
while ($row = $stmt->fetch()) {
|
||||
$name = $this->model->trimToNull($row['username'], true);
|
||||
if (null !== $name) {
|
||||
$userList[$name] = $row['id'];
|
||||
}
|
||||
|
||||
$ips = $this->model->trimToNull($row['ip']);
|
||||
if (null !== $ips) {
|
||||
foreach (explode(' ', $ips) as $ip) {
|
||||
$ip = trim($ip);
|
||||
if ($ip != '') {
|
||||
$ipList[$ip] = $row['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$email = $this->model->trimToNull($row['email']);
|
||||
$message = $this->model->trimToNull($row['message']);
|
||||
$expire = empty($row['expire']) ? null : $row['expire'];
|
||||
if (! isset($email) && ! isset($message) && ! isset($expire)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$otherList[$row['id']] = [
|
||||
'email' => $email,
|
||||
'message' => $message,
|
||||
'expire' => $expire,
|
||||
];
|
||||
}
|
||||
$this->model->otherList = $otherList;
|
||||
$this->model->userList = $userList;
|
||||
$this->model->ipList = $ipList;
|
||||
$this->c->Cache->set('banlist', [
|
||||
'otherList' => $otherList,
|
||||
'userList' => $userList,
|
||||
'ipList' => $ipList,
|
||||
]);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
41
app/Models/CensorshipList.php
Normal file
41
app/Models/CensorshipList.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class CensorshipList extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список цензуры из кеша/БД
|
||||
*
|
||||
* @return BanList
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('censorship')) {
|
||||
$list = $this->c->Cache->get('censorship');
|
||||
$this->searchList = $list['searchList'];
|
||||
$this->replaceList = $list['replaceList'];
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет цензуру при необходимости
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function censor($str)
|
||||
{
|
||||
if ($this->c->config->o_censoring == '1') {
|
||||
return (string) preg_replace($this->searchList, $this->replaceList, $str);
|
||||
} else {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
}
|
33
app/Models/CensorshipList/Load.php
Normal file
33
app/Models/CensorshipList/Load.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\CensorshipList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return CensorshipList
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
|
||||
$stmt = $this->c->DB->query('SELECT search_for, replace_with FROM ::censoring');
|
||||
$search = [];
|
||||
$replace = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$replace[] = $row['replace_with'];
|
||||
$search[] = '%(?<![\p{L}\p{N}])('.str_replace('\*', '[\p{L}\p{N}]*?', preg_quote($row['search_for'], '%')).')(?![\p{L}\p{N}])%iu';
|
||||
}
|
||||
$this->model->searchList = $search;
|
||||
$this->model->replaceList = $replace;
|
||||
$this->c->Cache->set('censorship', [
|
||||
'searchList' => $search,
|
||||
'replaceList' => $replace,
|
||||
]);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
23
app/Models/Config.php
Normal file
23
app/Models/Config.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\DataModel;
|
||||
|
||||
class Config extends DataModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из кеша/БД
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('config')) {
|
||||
$this->setAttrs($this->c->Cache->get('config'));
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
22
app/Models/Config/Load.php
Normal file
22
app/Models/Config/Load.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Config;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$config = $this->c->DB->query('SELECT conf_name, conf_value FROM ::config')->fetchAll(\PDO::FETCH_KEY_PAIR);
|
||||
$this->model->setAttrs($config);
|
||||
$this->c->Cache->set('config', $config);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
37
app/Models/Config/Save.php
Normal file
37
app/Models/Config/Save.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Config;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Save extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Сохраняет изменения модели в БД
|
||||
* Удаляет кеш
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$modified = $this->model->getModified();
|
||||
if (empty($modified)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$values = $this->model->getAttrs();
|
||||
foreach ($modified as $name) {
|
||||
$vars = [
|
||||
':value' => $values[$name],
|
||||
':name' => $name
|
||||
];
|
||||
//????
|
||||
$count = $this->c->DB->exec('UPDATE ::config SET conf_value=?s:value WHERE conf_name=?s:name', $vars);
|
||||
if ($count === 0) {
|
||||
$this->c->DB->exec('INSERT INTO ::config (conf_name, conf_value) VALUES (?s:name, ?s:value)', $vars);
|
||||
}
|
||||
}
|
||||
$this->c->Cache->delete('config');
|
||||
return $this->model;
|
||||
}
|
||||
}
|
212
app/Models/Cookie.php
Normal file
212
app/Models/Cookie.php
Normal file
|
@ -0,0 +1,212 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
use ForkBB\Models\User;
|
||||
use ForkBB\Core\Container;
|
||||
use RuntimeException;
|
||||
|
||||
class Cookie extends Model
|
||||
{
|
||||
const NAME = 'user';
|
||||
|
||||
/**
|
||||
* Флаг запрета записи свойств
|
||||
* @var bool
|
||||
*/
|
||||
protected $noSet = false;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array $options
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(array $options, Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->a = $options + [
|
||||
'prefix' => '',
|
||||
'domain' => '',
|
||||
'path' => '',
|
||||
'secure' => false,
|
||||
'time' => 31536000,
|
||||
'key1' => 'key1',
|
||||
'key2' => 'key2',
|
||||
];
|
||||
$this->init();
|
||||
$this->noSet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает куку
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param int $expire
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @param bool $secure
|
||||
* @param bool $httponly
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set($name, $value, $expire = 0, $path = null, $domain = null, $secure = false, $httponly = true)
|
||||
{
|
||||
$result = setcookie(
|
||||
$this->prefix . $name,
|
||||
$value,
|
||||
$expire,
|
||||
$path ?: $this->path,
|
||||
$domain ?: $this->domain,
|
||||
(bool) $this->secure || (bool) $secure,
|
||||
(bool) $httponly
|
||||
);
|
||||
if ($result) {
|
||||
$_COOKIE[$this->prefix . $name] = $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает значение куки
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
$name = $this->prefix . $name;
|
||||
return isset($_COOKIE[$name]) ? $this->c->Secury->replInvalidChars($_COOKIE[$name]) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет куку
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($name, $path = null, $domain = null)
|
||||
{
|
||||
$result = $this->set($name, '', 1, $path, $domain);
|
||||
if ($result) {
|
||||
unset($_COOKIE[$this->prefix . $name]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выделение данных из куки аутентификации
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
$ckUser = $this->get(self::NAME);
|
||||
|
||||
if (null === $ckUser
|
||||
|| ! preg_match('%^(\-)?(\d{1,10})_(\d{10})_([a-f\d]{32,})_([a-f\d]{32,})$%Di', $ckUser, $ms)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (2 > $ms[2]
|
||||
|| time() > $ms[3]
|
||||
|| ! hash_equals(
|
||||
$this->c->Secury->hmac($ms[1] . $ms[2] . $ms[3] . $ms[4], $this->key1),
|
||||
$ms[5]
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->uRemember = empty($ms[1]);
|
||||
$this->uId = (int) $ms[2];
|
||||
$this->uExpire = (int) $ms[3];
|
||||
$this->uHash = $ms[4];
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка хэша пароля
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyUser(User $user)
|
||||
{
|
||||
return $this->uId === (int) $user->id
|
||||
&& hash_equals(
|
||||
(string) $this->uHash,
|
||||
$this->c->Secury->hmac($user->password . $this->uExpire, $this->key2)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Установка куки аутентификации юзера
|
||||
*
|
||||
* @param User $user
|
||||
* @param bool $remember
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setUser(User $user, $remember = null)
|
||||
{
|
||||
if ($user->isGuest) {
|
||||
return $this->deleteUser();
|
||||
}
|
||||
|
||||
if ($remember
|
||||
|| (null === $remember
|
||||
&& $this->uId === (int) $user->id
|
||||
&& $this->uRemember
|
||||
)
|
||||
) {
|
||||
$expTime = time() + $this->time;
|
||||
$expire = $expTime;
|
||||
$pfx = '';
|
||||
} else {
|
||||
$expTime = time() + $this->c->config->o_timeout_visit;
|
||||
$expire = 0;
|
||||
$pfx = '-';
|
||||
}
|
||||
$passHash = $this->c->Secury->hmac($user->password . $expTime, $this->key2);
|
||||
$ckHash = $this->c->Secury->hmac($pfx . $user->id . $expTime . $passHash, $this->key1);
|
||||
|
||||
return $this->set(self::NAME, $pfx . $user->id . '_' . $expTime . '_' . $passHash . '_' . $ckHash, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление куки аутентификации юзера
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteUser()
|
||||
{
|
||||
if (null === $this->get(self::NAME)) {
|
||||
return true;
|
||||
} else {
|
||||
return $this->delete(self::NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значение для свойства
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $val
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __set($name, $val)
|
||||
{
|
||||
if ($this->noSet) {
|
||||
throw new RuntimeException('Model attributes in read-only mode');
|
||||
}
|
||||
parent::__set($name, $val);
|
||||
}
|
||||
}
|
25
app/Models/DBMap.php
Normal file
25
app/Models/DBMap.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class DBMap extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает карту БД из кеша/БД
|
||||
*
|
||||
* @return DBMap
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('db_map')) {
|
||||
$this->a = $this->c->Cache->get('db_map');
|
||||
} else {
|
||||
$map = $this->c->DB->getMap();
|
||||
$this->c->Cache->set('db_map', $map);
|
||||
$this->a = $map;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
91
app/Models/DataModel.php
Normal file
91
app/Models/DataModel.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Model;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class DataModel extends Model
|
||||
{
|
||||
/**
|
||||
* Массив флагов измененных свойств модели
|
||||
* @var array
|
||||
*/
|
||||
protected $modified = [];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(array $attrs, Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->a = $attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значения для свойств
|
||||
*
|
||||
* @param array $attrs
|
||||
*
|
||||
* @return DataModel
|
||||
*/
|
||||
public function setAttrs(array $attrs)
|
||||
{
|
||||
$this->a = $attrs; //????
|
||||
$this->modified = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значения свойств в массиве
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttrs()
|
||||
{
|
||||
return $this->a; //????
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив имен измененных свойств модели
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getModified()
|
||||
{
|
||||
return array_keys($this->modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обнуляет массив флагов измененных свойств модели
|
||||
*/
|
||||
public function resModified()
|
||||
{
|
||||
$this->modified = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значение для свойства
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $val
|
||||
*/
|
||||
public function __set($name, $val)
|
||||
{
|
||||
// запись свойства без отслеживания изменений
|
||||
if (strpos($name, '__') === 0) {
|
||||
return parent::__set(substr($name, 2), $val);
|
||||
}
|
||||
|
||||
$old = isset($this->a[$name]) ? $this->a[$name] : null;
|
||||
parent::__set($name, $val);
|
||||
if ($old !== $this->a[$name]) {
|
||||
$this->modified[$name] = true;
|
||||
}
|
||||
}
|
||||
}
|
54
app/Models/Forum.php
Normal file
54
app/Models/Forum.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\DataModel;
|
||||
use ForkBB\Core\Container;
|
||||
|
||||
class Forum extends DataModel
|
||||
{
|
||||
/**
|
||||
* @param array $attrs
|
||||
*
|
||||
* @return Forum
|
||||
*/
|
||||
public function replAtttrs(array $attrs)
|
||||
{
|
||||
foreach ($attrs as $key => $val) {
|
||||
$this->{'__' . $key} = $val; //????
|
||||
}
|
||||
$modified = array_diff(array_keys($this->modified), array_keys($attrs));
|
||||
$this->modified = [];
|
||||
foreach ($modified as $key) {
|
||||
$this->modified[$key] = true;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getSubforums()
|
||||
{
|
||||
$sub = [];
|
||||
if (! empty($this->a['subforums'])) {
|
||||
foreach ($this->a['subforums'] as $id) {
|
||||
$sub[$id] = $this->c->forums->forum($id);
|
||||
}
|
||||
}
|
||||
return $sub;
|
||||
}
|
||||
|
||||
protected function getDescendants()
|
||||
{
|
||||
$all = [];
|
||||
if (! empty($this->a['descendants'])) {
|
||||
foreach ($this->a['descendants'] as $id) {
|
||||
$all[$id] = $this->c->forums->forum($id);
|
||||
}
|
||||
}
|
||||
return $all;
|
||||
}
|
||||
|
||||
protected function getParent()
|
||||
{
|
||||
return $this->c->forums->forum($this->parent_forum_id);
|
||||
}
|
||||
}
|
62
app/Models/ForumList.php
Normal file
62
app/Models/ForumList.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
use RuntimeException;
|
||||
|
||||
class ForumList extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список доступных разделов для текущего пользователя из кеша/БД
|
||||
*
|
||||
* @return ForumList
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$mark = $this->c->Cache->get('forums_mark');
|
||||
if (empty($mark)) {
|
||||
$this->c->Cache->set('forums_mark', time());
|
||||
return $this->load();
|
||||
}
|
||||
|
||||
$result = $this->c->Cache->get('forums_' . $this->c->user->group_id);
|
||||
if (empty($result['time']) || $result['time'] < $mark) {
|
||||
return $this->load();
|
||||
}
|
||||
|
||||
$this->list = $result['list']; //????
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет доступность раздела
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAvailable($id)
|
||||
{
|
||||
return isset($this->list[$id]); //????
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return null|Forum
|
||||
*/
|
||||
public function forum($id)
|
||||
{
|
||||
if (isset($this->forums[$id])) {
|
||||
return $this->forums[$id];
|
||||
} elseif ($this->isAvailable($id)) {
|
||||
$forum = $this->c->ModelForum->setAttrs($this->list[$id]);
|
||||
$this->a['forums'][$id] = $forum; //????
|
||||
return $forum;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
93
app/Models/ForumList/Load.php
Normal file
93
app/Models/ForumList/Load.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\ForumList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $list = [];
|
||||
|
||||
/**
|
||||
* Заполняет модель данными из БД для текущего пользователя
|
||||
* Создает кеш
|
||||
*
|
||||
* @return ForumList
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$this->getList();
|
||||
$this->model->list = $this->list; //????
|
||||
$this->c->Cache->set('forums_' . $this->c->user->group_id, [
|
||||
'time' => time(),
|
||||
'list' => $this->list,
|
||||
]);
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает данные из БД
|
||||
*/
|
||||
protected function getList()
|
||||
{
|
||||
if ($this->c->user->g_read_board != '1') {
|
||||
return;
|
||||
}
|
||||
$list = [];
|
||||
$vars = [':gid' => $this->c->user->group_id];
|
||||
$sql = 'SELECT c.id AS cid, c.cat_name, f.id, f.forum_name, f.redirect_url, f.parent_forum_id,
|
||||
f.disp_position, fp.post_topics, fp.post_replies
|
||||
FROM ::categories AS c
|
||||
INNER JOIN ::forums AS f ON c.id=f.cat_id
|
||||
LEFT JOIN ::forum_perms AS fp ON (fp.group_id=?i:gid AND fp.forum_id=f.id)
|
||||
WHERE fp.read_forum IS NULL OR fp.read_forum=1
|
||||
ORDER BY c.disp_position, c.id, f.disp_position';
|
||||
$stmt = $this->c->DB->query($sql, $vars);
|
||||
while ($row = $stmt->fetch()) {
|
||||
$list[$row['id']] = $row;
|
||||
}
|
||||
if (empty($list)) {
|
||||
return;
|
||||
}
|
||||
$this->createList($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует список доступных разделов
|
||||
*
|
||||
* @param array $list
|
||||
* @param int $parent
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function createList(array $list, $parent = 0)
|
||||
{
|
||||
$sub = [];
|
||||
$all = [];
|
||||
foreach ($list as $id => $f) {
|
||||
if ($parent === $id || $parent !== $f['parent_forum_id']) {
|
||||
continue;
|
||||
}
|
||||
$sub[] = $id;
|
||||
$all = array_merge($this->createList($list, $id), $all);
|
||||
}
|
||||
if ($parent === 0) {
|
||||
if (empty($sub)) {
|
||||
return [];
|
||||
}
|
||||
$list[0]['id'] = $parent;
|
||||
$list[0]['ready'] = true;
|
||||
}
|
||||
$all = array_merge($sub, $all);
|
||||
$list[$parent]['subforums'] = $sub ?: null;
|
||||
$list[$parent]['descendants'] = $all ?: null;
|
||||
|
||||
$this->list[$parent] = array_filter($list[$parent], function($val) {
|
||||
return $val !== null;
|
||||
});
|
||||
return $all;
|
||||
}
|
||||
}
|
132
app/Models/ForumList/LoadTree.php
Normal file
132
app/Models/ForumList/LoadTree.php
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\ForumList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class LoadTree extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Загружает данные в модели разделов для указанного раздела и всех его потомков
|
||||
*
|
||||
* @param int $rootId
|
||||
*
|
||||
* @return null|Forum
|
||||
*/
|
||||
public function loadTree($rootId)
|
||||
{
|
||||
$root = $this->model->forum($rootId);
|
||||
if (null === $root) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$list = [];
|
||||
if (! $root->ready) {
|
||||
$list[] = $rootId;
|
||||
}
|
||||
foreach ($root->descendants as $id => $descendant) {
|
||||
if (! $descendant->ready) {
|
||||
$list[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadData($list);
|
||||
|
||||
if (! $this->c->user->isGuest) {
|
||||
$this->checkForNew(array_keys($root->descendants)); //????
|
||||
}
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружает данные из БД по списку id разделов
|
||||
*
|
||||
* @param array $list
|
||||
*/
|
||||
public function loadData(array $list)
|
||||
{
|
||||
if (empty($list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':uid' => $this->c->user->id,
|
||||
':forums' => $list,
|
||||
];
|
||||
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT f.id, f.forum_desc, f.moderators, f.num_topics, f.sort_by,
|
||||
f.num_posts, f.last_post, f.last_post_id, f.last_poster, f.last_topic
|
||||
FROM ::forums AS f
|
||||
WHERE id IN (?ai:forums)';
|
||||
} elseif ($this->c->config->o_forum_subscriptions == '1') {
|
||||
$sql = 'SELECT f.id, f.forum_desc, f.moderators, f.num_topics, f.sort_by,
|
||||
f.num_posts, f.last_post, f.last_post_id, f.last_poster, f.last_topic,
|
||||
mof.mf_mark_all_read, s.user_id AS is_subscribed
|
||||
FROM ::forums AS f
|
||||
LEFT JOIN ::forum_subscriptions AS s ON (s.user_id=?i:uid AND s.forum_id=f.id)
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND mof.fid=f.id)
|
||||
WHERE f.id IN (?ai:forums)';
|
||||
} else {
|
||||
$sql = 'SELECT f.id, f.forum_desc, f.moderators, f.num_topics, f.sort_by,
|
||||
f.num_posts, f.last_post, f.last_post_id, f.last_poster, f.last_topic,
|
||||
mof.mf_mark_all_read
|
||||
FROM ::forums AS f
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:id AND mof.fid=f.id)
|
||||
WHERE f.id IN (?ai:forums)';
|
||||
}
|
||||
|
||||
$stmt = $this->c->DB->query($sql, $vars);
|
||||
while ($cur = $stmt->fetch()) {
|
||||
$this->model->forum($cur['id'])->replAtttrs($cur)->ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет наличие новых сообщений в разделах по списку id
|
||||
*
|
||||
* @param array $list
|
||||
*/
|
||||
protected function checkForNew(array $list)
|
||||
{
|
||||
if (empty($list) || $this->c->user->isGuest) {
|
||||
return;
|
||||
}
|
||||
|
||||
// предварительная проверка разделов
|
||||
$time = [];
|
||||
$max = max((int) $this->c->user->last_visit, (int) $this->c->user->u_mark_all_read);
|
||||
foreach ($list as $id) {
|
||||
$forum = $this->model->forum($id);
|
||||
$t = max($max, (int) $forum->mf_mark_all_read);
|
||||
if ($forum->last_post > $t) {
|
||||
$time[$id] = $t;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($time)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// проверка по темам
|
||||
$vars = [
|
||||
':uid' => $this->c->user->id,
|
||||
':forums' => array_keys($time),
|
||||
':max' => $max,
|
||||
];
|
||||
$sql = 'SELECT t.forum_id, t.last_post
|
||||
FROM ::topics AS t
|
||||
LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND mot.tid=t.id)
|
||||
WHERE t.forum_id IN(?ai:forums)
|
||||
AND t.last_post>?i:max
|
||||
AND t.moved_to IS NULL
|
||||
AND (mot.mt_last_visit IS NULL OR t.last_post>mot.mt_last_visit)';
|
||||
$stmt = $this->c->DB->query($sql, $vars);
|
||||
while ($cur = $stmt->fetch()) {
|
||||
if ($cur['last_post'] > $time[$cur['forum_id']]) {
|
||||
$this->model->forum($cur['forum_id'])->newMessages = true; //????
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
app/Models/MethodModel.php
Normal file
33
app/Models/MethodModel.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
abstract class MethodModel
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Модель
|
||||
* @var Model
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Model $model
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Model $model, Container $container)
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->c = $container;
|
||||
}
|
||||
}
|
115
app/Models/Model.php
Normal file
115
app/Models/Model.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class Model
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Данные модели
|
||||
* @var array
|
||||
*/
|
||||
protected $a = [];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет наличие свойства
|
||||
*
|
||||
* @param mixed $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->a[$name]); //???? array_key_exists($name, $this->a)
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет свойство
|
||||
*
|
||||
* @param mixed $name
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
unset($this->a[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значение для свойства
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $val
|
||||
*/
|
||||
public function __set($name, $val)
|
||||
{
|
||||
$method = 'set' . ucfirst($name);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($val);
|
||||
} else {
|
||||
$this->a[$name] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение свойства
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$method = 'get' . ucfirst($name);
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method();
|
||||
} else {
|
||||
return isset($this->a[$name]) ? $this->a[$name] : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет подгружаемый метод при его наличии
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $args
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, array $args)
|
||||
{
|
||||
$key = str_replace(['ForkBB\\', '\\'], '', get_class($this));
|
||||
|
||||
if (empty($this->c->METHODS[$key][$name])) {
|
||||
throw new RuntimeException("The {$name} method was not found");
|
||||
}
|
||||
|
||||
$link = explode(':', $this->c->METHODS[$key][$name], 2);
|
||||
$factory = new $link[0]($this, $this->c);
|
||||
|
||||
if (isset($link[1])) {
|
||||
return $factory->{$link[1]}(...$args);
|
||||
} else {
|
||||
return $factory->$name(...$args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,71 +3,60 @@
|
|||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Model;
|
||||
use ForkBB\Models\User;
|
||||
use ForkBB\Models\Pages\Page;
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Online
|
||||
class Online extends Model
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Флаг выполнения
|
||||
* @var bool
|
||||
*/
|
||||
protected $done = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param array $config
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
parent::__construct($container);
|
||||
$this->users = [];
|
||||
$this->guests = [];
|
||||
$this->bots = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка данных пользователей онлайн
|
||||
* Обновление данных текущего пользователя
|
||||
* Возврат данных по пользователям онлайн
|
||||
*
|
||||
* @param Page $page
|
||||
* @return array
|
||||
*/
|
||||
public function handle(Page $page)
|
||||
public function calc(Page $page)
|
||||
{
|
||||
if ($this->done) {
|
||||
return [[], [], []]; //????
|
||||
return;
|
||||
}
|
||||
$this->done = true;
|
||||
|
||||
// string|null bool bool
|
||||
list($position, $type, $filter) = $page->getDataForOnline(); //???? возможно стоит возвращать полное имя страницы для отображение
|
||||
$position = $page->onlinePos;
|
||||
if (null === $position) {
|
||||
return [[], [], []]; //????
|
||||
return;
|
||||
}
|
||||
$type = $page->onlineType;
|
||||
$filter = $page->onlineFilter;
|
||||
|
||||
$this->updateUser($position);
|
||||
|
||||
$all = 0;
|
||||
$now = time();
|
||||
$tOnline = $now - $this->config['o_timeout_online'];
|
||||
$tVisit = $now - $this->config['o_timeout_visit'];
|
||||
$users = $guests = $bots = [];
|
||||
$all = 0;
|
||||
$now = time();
|
||||
$tOnline = $now - $this->c->config->o_timeout_online;
|
||||
$tVisit = $now - $this->c->config->o_timeout_visit;
|
||||
$users = [];
|
||||
$guests = [];
|
||||
$bots = [];
|
||||
$deleteG = false;
|
||||
$deleteU = false;
|
||||
$setIdle = false;
|
||||
|
||||
if ($this->config['o_users_online'] == '1' && $type) {
|
||||
if ($this->c->config->o_users_online == '1' && $type) {
|
||||
$stmt = $this->c->DB->query('SELECT user_id, ident, logged, idle, o_position, o_name FROM ::online ORDER BY logged');
|
||||
} elseif ($type) {
|
||||
$stmt = $this->c->DB->query('SELECT user_id, ident, logged, idle FROM ::online ORDER BY logged');
|
||||
|
@ -142,16 +131,19 @@ class Online
|
|||
}
|
||||
|
||||
// обновление максимального значение пользоватеелй онлайн
|
||||
if ($this->config['st_max_users'] < $all) {
|
||||
$this->c->DB->exec('UPDATE ::config SET conf_value=?s:value WHERE conf_name=?s:name', [':value' => $all, ':name' => 'st_max_users']);
|
||||
$this->c->DB->exec('UPDATE ::config SET conf_value=?s:value WHERE conf_name=?s:name', [':value' => $now, ':name' => 'st_max_users_time']);
|
||||
$this->c->{'config update'};
|
||||
if ($this->c->config->st_max_users < $all) {
|
||||
$this->c->config->st_max_users = $all;
|
||||
$this->c->config->st_max_users_time = $now;
|
||||
$this->c->config->save();
|
||||
}
|
||||
return [$users, $guests, $bots];
|
||||
$this->users = $users;
|
||||
$this->guests = $guests;
|
||||
$this->bots = $bots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновление данных текущего пользователя
|
||||
*
|
||||
* @param string $position
|
||||
*/
|
||||
protected function updateUser($position)
|
||||
|
|
|
@ -1,118 +1,181 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Model;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class Page
|
||||
abstract class Page extends Model
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Конфигурация форума
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* HTTP статус ответа для данной страницы
|
||||
* @var int
|
||||
*/
|
||||
protected $httpStatus = 200;
|
||||
|
||||
/**
|
||||
* HTTP заголовки отличные от статуса
|
||||
* @var array
|
||||
*/
|
||||
protected $httpHeaders = [];
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl;
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации
|
||||
* @var string
|
||||
*/
|
||||
protected $index = 'index';
|
||||
|
||||
/**
|
||||
* Массив титула страницы
|
||||
* @var array
|
||||
*/
|
||||
protected $titles = [];
|
||||
|
||||
/**
|
||||
* Подготовленные данные для шаблона
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Массив info, success, warning, error, validation информации
|
||||
* @var array
|
||||
*/
|
||||
protected $iswev = [];
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = '';
|
||||
|
||||
/**
|
||||
* Тип обработки пользователей онлайн
|
||||
* Если false, то идет обновление данных
|
||||
* Если true, то идет возврат данных (смотрите $onlineFilter)
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineType = false;
|
||||
|
||||
/**
|
||||
* Тип возврата данных при onlineType === true
|
||||
* Если true, то из online должны вернутся только пользователи находящиеся на этой же странице
|
||||
* Если false, то все пользователи online
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineFilter = true;
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots;
|
||||
|
||||
/**
|
||||
* Переменная для link rel="canonical"
|
||||
* @var string
|
||||
*/
|
||||
protected $canonical;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
parent::__construct($container);
|
||||
|
||||
$container->Lang->load('common');
|
||||
|
||||
$this->fIndex = 'index'; # string Указатель на активный пункт навигации
|
||||
$this->httpStatus = 200; # int HTTP статус ответа для данной страницы
|
||||
$this->httpHeaders = []; # array HTTP заголовки отличные от статуса
|
||||
# $this->nameTpl = null; # null|string Имя шаблона
|
||||
# $this->titles = []; # array Массив титула страницы | setTitles()
|
||||
$this->fIswev = []; # array Массив info, success, warning, error, validation информации
|
||||
# $this->onlinePos = ''; # null|string Позиция для таблицы онлайн текущего пользователя
|
||||
$this->onlineType = false; # bool Тип обработки пользователей онлайн
|
||||
# Если false, то идет обновление данных
|
||||
# Если true, то идет возврат данных (смотрите onlineFilter)
|
||||
$this->onlineFilter = true; # bool Тип возврата данных при onlineType === true
|
||||
# Если true, то из online должны вернутся только пользователи находящиеся на этой же странице
|
||||
# Если false, то все пользователи online
|
||||
# $this->robots = ''; # string Переменная для meta name="robots"
|
||||
# $this->canonical = ''; # string Переменная для link rel="canonical"
|
||||
|
||||
$this->fTitle = $container->config->o_board_title;
|
||||
$this->fDescription = $container->config->o_board_desc;
|
||||
$this->fAnnounce = $container->config->o_announcement_message;
|
||||
$this->fRootLink = $container->Router->link('Index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function prepare()
|
||||
{
|
||||
$this->fNavigation = $this->fNavigation();
|
||||
$this->maintenance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив ссылок с описанием для построения навигации
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function fNavigation()
|
||||
{
|
||||
$user = $this->c->user;
|
||||
$r = $this->c->Router;
|
||||
|
||||
$nav = [
|
||||
'index' => [$r->link('Index'), __('Index')]
|
||||
];
|
||||
|
||||
if ($user->g_read_board == '1' && $user->g_view_users == '1') {
|
||||
$nav['userlist'] = [$r->link('Userlist'), __('User list')];
|
||||
}
|
||||
|
||||
if ($this->c->config->o_rules == '1' && (! $user->isGuest || $user->g_read_board == '1' || $this->c->config->o_regs_allow == '1')) {
|
||||
$nav['rules'] = [$r->link('Rules'), __('Rules')];
|
||||
}
|
||||
|
||||
if ($user->g_read_board == '1' && $user->g_search == '1') {
|
||||
$nav['search'] = [$r->link('Search'), __('Search')];
|
||||
}
|
||||
|
||||
if ($user->isGuest) {
|
||||
$nav['register'] = [$r->link('Register'), __('Register')];
|
||||
$nav['login'] = [$r->link('Login'), __('Login')];
|
||||
} else {
|
||||
$nav['profile'] = [$r->link('User', [
|
||||
'id' => $user->id,
|
||||
'name' => $user->username,
|
||||
]), __('Profile')];
|
||||
// New PMS
|
||||
if ($this->c->config->o_pms_enabled == '1' && ($user->isAdmin || $user->messages_new > 0)) { //????
|
||||
$nav['pmsnew'] = ['pmsnew.php', __('PM')]; //'<li id="nav"'.((PUN_ACTIVE_PAGE == 'pms_new' || $user['messages_new'] > 0) ? ' class="isactive"' : '').'><a href="pmsnew.php">'.__('PM').(($user['messages_new'] > 0) ? ' (<span'.((empty($this->c->config->o_pms_flasher) || PUN_ACTIVE_PAGE == 'pms_new') ? '' : ' class="remflasher"' ).'>'.$user['messages_new'].'</span>)' : '').'</a></li>';
|
||||
}
|
||||
// New PMS
|
||||
|
||||
if ($user->isAdmMod) {
|
||||
$nav['admin'] = [$r->link('Admin'), __('Admin')];
|
||||
}
|
||||
|
||||
$nav['logout'] = [$r->link('Logout', [
|
||||
'token' => $this->c->Csrf->create('Logout'),
|
||||
]), __('Logout')];
|
||||
}
|
||||
|
||||
if ($user->g_read_board == '1' && $this->c->config->o_additional_navlinks != '') {
|
||||
// position|name|link[|id]\n
|
||||
if (preg_match_all('%^(\d+)\|([^\|\n\r]+)\|([^\|\n\r]+)(?:\|([^\|\n\r]+))?$%m', $this->c->config->o_additional_navlinks."\n", $matches)) {
|
||||
$k = count($matches[0]);
|
||||
for ($i = 0; $i < $k; ++$i) {
|
||||
if (empty($matches[4][$i])) {
|
||||
$matches[4][$i] = 'extra' . $i;
|
||||
}
|
||||
if (isset($nav[$matches[4][$i]])) {
|
||||
$nav[$matches[4][$i]] = [$matches[3][$i], $matches[2][$i]];
|
||||
} else {
|
||||
$nav = array_merge(
|
||||
array_slice($nav, 0, $matches[1][$i]),
|
||||
[$matches[4][$i] => [$matches[3][$i], $matches[2][$i]]],
|
||||
array_slice($nav, $matches[1][$i])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $nav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод информации о режиме обслуживания для админа
|
||||
*/
|
||||
protected function maintenance()
|
||||
{
|
||||
if ($this->c->config->o_maintenance == '1' && $this->c->user->isAdmin) {
|
||||
$this->a['fIswev']['w']['maintenance'] = __('Maintenance mode enabled', $this->c->Router->link('AdminOptions', ['#' => 'maintenance']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает title страницы
|
||||
* $this->pageTitle
|
||||
*
|
||||
* @param array $titles
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPageTitle(array $titles = [])
|
||||
{
|
||||
if (empty($titles)) {
|
||||
$titles = $this->titles;
|
||||
}
|
||||
$titles[] = $this->c->config->o_board_title;
|
||||
return implode(__('Title separator'), $titles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массива заголовков страницы
|
||||
* $this->pageHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPageHeaders()
|
||||
{
|
||||
$headers = ['link rel="stylesheet" type="text/css" href="' . $this->c->PUBLIC_URL . '/style/' . $this->c->user->style . '/style.css' . '"'];
|
||||
if ($this->robots) {
|
||||
$headers[] = 'meta name="robots" content="' . $this->robots . '"';
|
||||
}
|
||||
if ($this->canonical) {
|
||||
$headers[] = 'link rel="canonical" href="' . $this->canonical . '"';
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает HTTP заголовки страницы
|
||||
* $this->httpHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function httpHeaders()
|
||||
protected function getHttpHeaders()
|
||||
{
|
||||
$headers = $this->httpHeaders;
|
||||
$headers = $this->a['httpHeaders'];
|
||||
if (! empty($status = $this->httpStatus())) {
|
||||
$headers[] = $status;
|
||||
}
|
||||
|
@ -121,6 +184,7 @@ abstract class Page
|
|||
|
||||
/**
|
||||
* Возвращает HTTP статус страницы или null
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function httpStatus()
|
||||
|
@ -147,190 +211,25 @@ abstract class Page
|
|||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг готовности данных
|
||||
* @return bool
|
||||
* Дописывает в массив титула страницы новый элемент
|
||||
* $this->titles
|
||||
*
|
||||
* @param string @val
|
||||
*/
|
||||
public function isReady()
|
||||
public function setTitles($val)
|
||||
{
|
||||
return ! empty($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает имя шаблона
|
||||
* @return string
|
||||
*/
|
||||
public function getNameTpl()
|
||||
{
|
||||
return $this->nameTpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return [
|
||||
'pageTitle' => $this->pageTitle(),
|
||||
'pageHeaders' => $this->pageHeaders(),
|
||||
'fTitle' => $this->config['o_board_title'],
|
||||
'fDescription' => $this->config['o_board_desc'],
|
||||
'fNavigation' => $this->fNavigation(),
|
||||
'fIndex' => $this->index,
|
||||
'fAnnounce' => $this->fAnnounce(),
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
'fIswev' => $this->getIswev(),
|
||||
] + $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возврат info, success, warning, error, validation информации
|
||||
* @return array
|
||||
*/
|
||||
protected function getIswev()
|
||||
{
|
||||
if ($this->config['o_maintenance'] == '1' && $this->c->user->isAdmin) {
|
||||
$this->iswev['w']['maintenance'] = __('Maintenance mode enabled', $this->c->Router->link('AdminOptions', ['#' => 'maintenance']));
|
||||
}
|
||||
return $this->iswev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Установка info, success, warning, error, validation информации из вне
|
||||
* @param array $iswev
|
||||
* @return Page
|
||||
*/
|
||||
public function setIswev(array $iswev)
|
||||
{
|
||||
$this->iswev = $iswev;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует title страницы
|
||||
* @param array $titles
|
||||
* @return string
|
||||
*/
|
||||
protected function pageTitle(array $titles = [])
|
||||
{
|
||||
if (empty($titles)) {
|
||||
$titles = $this->titles;
|
||||
}
|
||||
$titles[] = $this->config['o_board_title'];
|
||||
return implode(__('Title separator'), $titles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация массива заголовков страницы
|
||||
* @return array
|
||||
*/
|
||||
protected function pageHeaders()
|
||||
{
|
||||
$headers = ['link rel="stylesheet" type="text/css" href="' . $this->c->PUBLIC_URL . '/style/' . $this->c->user->style . '/style.css' . '"'];
|
||||
if ($this->robots) {
|
||||
$headers[] = 'meta name="robots" content="' . $this->robots . '"';
|
||||
}
|
||||
if ($this->canonical) {
|
||||
$headers[] = 'link rel="canonical" href="' . $this->canonical . '"';
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текст объявления или null
|
||||
* @return null|string
|
||||
*/
|
||||
protected function fAnnounce()
|
||||
{
|
||||
return empty($this->config['o_announcement']) ? null : $this->config['o_announcement_message'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив ссылок с описанием для построения навигации
|
||||
* @return array
|
||||
*/
|
||||
protected function fNavigation()
|
||||
{
|
||||
$user = $this->c->user;
|
||||
$r = $this->c->Router;
|
||||
|
||||
$nav = [
|
||||
'index' => [$r->link('Index'), __('Index')]
|
||||
];
|
||||
|
||||
if ($user->gReadBoard == '1' && $user->gViewUsers == '1') {
|
||||
$nav['userlist'] = [$r->link('Userlist'), __('User list')];
|
||||
}
|
||||
|
||||
if ($this->config['o_rules'] == '1' && (! $user->isGuest || $user->gReadBoard == '1' || $this->config['o_regs_allow'] == '1')) {
|
||||
$nav['rules'] = [$r->link('Rules'), __('Rules')];
|
||||
}
|
||||
|
||||
if ($user->gReadBoard == '1' && $user->gSearch == '1') {
|
||||
$nav['search'] = [$r->link('Search'), __('Search')];
|
||||
}
|
||||
|
||||
if ($user->isGuest) {
|
||||
$nav['register'] = [$r->link('Register'), __('Register')];
|
||||
$nav['login'] = [$r->link('Login'), __('Login')];
|
||||
if (empty($this->a['titles'])) {
|
||||
$this->a['titles'] = [$val];
|
||||
} else {
|
||||
$nav['profile'] = [$r->link('User', [
|
||||
'id' => $user->id,
|
||||
'name' => $user->username,
|
||||
]), __('Profile')];
|
||||
// New PMS
|
||||
if ($this->config['o_pms_enabled'] == '1' && ($user->isAdmin || $user->messagesNew > 0)) { //????
|
||||
$nav['pmsnew'] = ['pmsnew.php', __('PM')]; //'<li id="nav"'.((PUN_ACTIVE_PAGE == 'pms_new' || $user['messages_new'] > 0) ? ' class="isactive"' : '').'><a href="pmsnew.php">'.__('PM').(($user['messages_new'] > 0) ? ' (<span'.((empty($this->config['o_pms_flasher']) || PUN_ACTIVE_PAGE == 'pms_new') ? '' : ' class="remflasher"' ).'>'.$user['messages_new'].'</span>)' : '').'</a></li>';
|
||||
}
|
||||
// New PMS
|
||||
|
||||
if ($user->isAdmMod) {
|
||||
$nav['admin'] = [$r->link('Admin'), __('Admin')];
|
||||
}
|
||||
|
||||
$nav['logout'] = [$r->link('Logout', [
|
||||
'token' => $this->c->Csrf->create('Logout'),
|
||||
]), __('Logout')];
|
||||
$this->a['titles'][] = $val;
|
||||
}
|
||||
|
||||
if ($user->gReadBoard == '1' && $this->config['o_additional_navlinks'] != '') {
|
||||
// position|name|link[|id]\n
|
||||
if (preg_match_all('%^(\d+)\|([^\|\n\r]+)\|([^\|\n\r]+)(?:\|([^\|\n\r]+))?$%m', $this->config['o_additional_navlinks']."\n", $matches)) {
|
||||
$k = count($matches[0]);
|
||||
for ($i = 0; $i < $k; ++$i) {
|
||||
if (empty($matches[4][$i])) {
|
||||
$matches[4][$i] = 'extra' . $i;
|
||||
}
|
||||
if (isset($nav[$matches[4][$i]])) {
|
||||
$nav[$matches[4][$i]] = [$matches[3][$i], $matches[2][$i]];
|
||||
} else {
|
||||
$nav = array_merge(
|
||||
array_slice($nav, 0, $matches[1][$i]),
|
||||
[$matches[4][$i] => [$matches[3][$i], $matches[2][$i]]],
|
||||
array_slice($nav, $matches[1][$i])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $nav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возращает данные для управления обработкой пользователей онлайн
|
||||
* @param bool $short
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getDataForOnline($short = false)
|
||||
{
|
||||
return $short
|
||||
? null !== $this->onlinePos
|
||||
: [$this->onlinePos, $this->onlineType, $this->onlineFilter];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает размер в байтах, Кбайтах, ...
|
||||
*
|
||||
* @param int $size
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function size($size)
|
||||
|
@ -346,8 +245,10 @@ abstract class Page
|
|||
|
||||
/**
|
||||
* Возвращает число в формате языка текущего пользователя
|
||||
*
|
||||
* @param mixed $number
|
||||
* @param int $decimals
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function number($number, $decimals = 0)
|
||||
|
@ -357,15 +258,16 @@ abstract class Page
|
|||
: 'not a number';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает время в формате текущего пользователя
|
||||
*
|
||||
* @param int|string $timestamp
|
||||
* @param bool $dateOnly
|
||||
* @param string $dateFormat
|
||||
* @param string $timeFormat
|
||||
* @param bool $timeOnly
|
||||
* @param bool $noText
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function time($timestamp, $dateOnly = false, $dateFormat = null, $timeFormat = null, $timeOnly = false, $noText = false)
|
||||
|
@ -380,10 +282,10 @@ abstract class Page
|
|||
$timestamp += $diff;
|
||||
|
||||
if (null === $dateFormat) {
|
||||
$dateFormat = $this->c->DATE_FORMATS[$user->dateFormat];
|
||||
$dateFormat = $this->c->DATE_FORMATS[$user->date_format];
|
||||
}
|
||||
if(null === $timeFormat) {
|
||||
$timeFormat = $this->c->TIME_FORMATS[$user->timeFormat];
|
||||
$timeFormat = $this->c->TIME_FORMATS[$user->time_format];
|
||||
}
|
||||
|
||||
$date = gmdate($dateFormat, $timestamp);
|
||||
|
@ -406,29 +308,4 @@ abstract class Page
|
|||
return $date . ' ' . gmdate($timeFormat, $timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет цензуру при необходимости
|
||||
* @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
|
||||
* @param array $arguments
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __call($name, array $arguments)
|
||||
{
|
||||
throw new RuntimeException("'{$name}' method not found.");
|
||||
}
|
||||
}
|
90
app/Models/Pages/Admin.php
Normal file
90
app/Models/Pages/Admin.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
abstract class Admin extends Page
|
||||
{
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
|
||||
$this->aIndex = 'index'; # string Указатель на активный пункт навигации в меню админки
|
||||
$this->fIndex = 'admin';
|
||||
$this->onlinePos = 'admin';
|
||||
$this->robots = 'noindex, nofollow';
|
||||
|
||||
$container->Lang->load('admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function prepare()
|
||||
{
|
||||
$this->aNavigation = $this->aNavigation();
|
||||
parent::prepare();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив ссылок с описанием для построения навигации админки
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function aNavigation()
|
||||
{
|
||||
$user = $this->c->user;
|
||||
$r = $this->c->Router;
|
||||
|
||||
$nav = [
|
||||
'Moderator menu' => [
|
||||
'index' => [$r->link('Admin'), __('Admin index')],
|
||||
'users' => ['admin_users.php', __('Users')],
|
||||
],
|
||||
];
|
||||
if ($user->isAdmin || $user->g_mod_ban_users == '1') {
|
||||
$nav['Moderator menu']['bans'] = ['admin_bans.php', __('Bans')];
|
||||
}
|
||||
if ($user->isAdmin || $this->c->config->o_report_method == '0' || $this->c->config->o_report_method == '2') {
|
||||
$nav['Moderator menu']['reports'] = ['admin_reports.php', __('Reports')];
|
||||
}
|
||||
|
||||
if ($user->isAdmin) {
|
||||
$nav['Admin menu'] = [
|
||||
'options' => ['admin_options.php', __('Admin options')],
|
||||
'permissions' => ['admin_permissions.php', __('Permissions')],
|
||||
'categories' => ['admin_categories.php', __('Categories')],
|
||||
'forums' => ['admin_forums.php', __('Forums')],
|
||||
'groups' => [$r->link('AdminGroups'), __('User groups')],
|
||||
'censoring' => ['admin_censoring.php', __('Censoring')],
|
||||
'maintenance' => ['admin_maintenance.php', __('Maintenance')]
|
||||
];
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает title страницы
|
||||
* $this->pageTitle
|
||||
*
|
||||
* @param array $titles
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPageTitle(array $titles = [])
|
||||
{
|
||||
if (empty($titles)) {
|
||||
$titles = $this->titles;
|
||||
}
|
||||
$titles[] = __('Admin title');
|
||||
return parent::getPageTitle($titles);
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages\Admin;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Pages\Page;
|
||||
|
||||
abstract class Admin extends Page
|
||||
{
|
||||
/**
|
||||
* Указатель на активный пункт навигации админки
|
||||
* @var string
|
||||
*/
|
||||
protected $adminIndex;
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации
|
||||
* @var string
|
||||
*/
|
||||
protected $index = 'admin';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var string
|
||||
*/
|
||||
protected $onlinePos = 'admin';
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots = 'noindex, nofollow';
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$container->Lang->load('admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$data = parent::getData();
|
||||
$data['aNavigation'] = $this->aNavigation();
|
||||
$data['aIndex'] = $this->adminIndex;
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует title страницы
|
||||
* @param array $titles
|
||||
* @return string
|
||||
*/
|
||||
protected function pageTitle(array $titles = [])
|
||||
{
|
||||
$titles = $this->titles;
|
||||
$titles[] = __('Admin title');
|
||||
return parent::pageTitle($titles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив ссылок с описанием для построения навигации админки
|
||||
* @return array
|
||||
*/
|
||||
protected function aNavigation()
|
||||
{
|
||||
$user = $this->c->user;
|
||||
$r = $this->c->Router;
|
||||
|
||||
$nav = [
|
||||
'Moderator menu' => [
|
||||
'index' => [$r->link('Admin'), __('Admin index')],
|
||||
'users' => ['admin_users.php', __('Users')],
|
||||
],
|
||||
];
|
||||
if ($user->isAdmin || $user->gModBanUsers == '1') {
|
||||
$nav['Moderator menu']['bans'] = ['admin_bans.php', __('Bans')];
|
||||
}
|
||||
if ($user->isAdmin || $this->config['o_report_method'] == '0' || $this->config['o_report_method'] == '2') {
|
||||
$nav['Moderator menu']['reports'] = ['admin_reports.php', __('Reports')];
|
||||
}
|
||||
|
||||
if ($user->isAdmin) {
|
||||
$nav['Admin menu'] = [
|
||||
'options' => ['admin_options.php', __('Admin options')],
|
||||
'permissions' => ['admin_permissions.php', __('Permissions')],
|
||||
'categories' => ['admin_categories.php', __('Categories')],
|
||||
'forums' => ['admin_forums.php', __('Forums')],
|
||||
'groups' => [$r->link('AdminGroups'), __('User groups')],
|
||||
'censoring' => ['admin_censoring.php', __('Censoring')],
|
||||
'maintenance' => ['admin_maintenance.php', __('Maintenance')]
|
||||
];
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,21 +4,10 @@ namespace ForkBB\Models\Pages\Admin;
|
|||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Core\Validator;
|
||||
use ForkBB\Models\Pages\Admin;
|
||||
|
||||
class Groups extends Admin
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'admin/groups';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации админки
|
||||
* @var string
|
||||
*/
|
||||
protected $adminIndex = 'groups';
|
||||
|
||||
/**
|
||||
* Массив групп
|
||||
* @var array
|
||||
|
@ -45,6 +34,7 @@ class Groups extends Admin
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
|
@ -66,6 +56,7 @@ class Groups extends Admin
|
|||
}
|
||||
}
|
||||
}
|
||||
$this->aIndex = 'groups';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,6 +75,7 @@ class Groups extends Admin
|
|||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function view()
|
||||
|
@ -109,23 +101,23 @@ class Groups extends Admin
|
|||
|
||||
$this->c->Lang->load('admin_groups');
|
||||
|
||||
$this->data = [
|
||||
'formActionNew' => $this->c->Router->link('AdminGroupsNew'),
|
||||
'formTokenNew' => $this->c->Csrf->create('AdminGroupsNew'),
|
||||
'formActionDefault' => $this->c->Router->link('AdminGroupsDefault'),
|
||||
'formTokenDefault' => $this->c->Csrf->create('AdminGroupsDefault'),
|
||||
'defaultGroup' => $this->config['o_default_user_group'],
|
||||
'groupsNew' => $groupsNew,
|
||||
'groupsDefault' => $groupsDefault,
|
||||
'groupsList' => $groupsList,
|
||||
'tabindex' => 0,
|
||||
];
|
||||
$this->nameTpl = 'admin/groups';
|
||||
$this->formActionNew = $this->c->Router->link('AdminGroupsNew');
|
||||
$this->formTokenNew = $this->c->Csrf->create('AdminGroupsNew');
|
||||
$this->formActionDefault = $this->c->Router->link('AdminGroupsDefault');
|
||||
$this->formTokenDefault = $this->c->Csrf->create('AdminGroupsDefault');
|
||||
$this->defaultGroup = $this->c->config->o_default_user_group;
|
||||
$this->groupsNew = $groupsNew;
|
||||
$this->groupsDefault = $groupsDefault;
|
||||
$this->groupsList = $groupsList;
|
||||
$this->tabindex = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает группу по умолчанию
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function defaultPost()
|
||||
|
@ -138,18 +130,20 @@ class Groups extends Admin
|
|||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
return $this->view();
|
||||
}
|
||||
$this->c->DB->exec('UPDATE ::config SET conf_value=?s:id WHERE conf_name=\'o_default_user_group\'', [':id' => $v->defaultgroup]);
|
||||
$this->c->{'config update'};
|
||||
return $this->c->Redirect->setPage('AdminGroups')->setMessage(__('Default group redirect'));
|
||||
$this->c->config->o_default_user_group = $v->defaultgroup;
|
||||
$this->c->config->save();
|
||||
return $this->c->Redirect->page('AdminGroups')->message(__('Default group redirect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает данные для создание группы
|
||||
* Создает новую группу
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function newPost(array $args)
|
||||
|
@ -163,7 +157,7 @@ class Groups extends Admin
|
|||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
return $this->view();
|
||||
} else {
|
||||
return $this->edit(['id' => $v->basegroup, '_new' => true]);
|
||||
|
@ -175,7 +169,9 @@ class Groups extends Admin
|
|||
|
||||
/**
|
||||
* Подготавливает данные для шаблона редактирования группы
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function edit(array $args)
|
||||
|
@ -203,20 +199,20 @@ class Groups extends Admin
|
|||
|
||||
$this->c->Lang->load('admin_groups');
|
||||
|
||||
$this->data = [
|
||||
'formAction' => $this->c->Router->link($marker, $vars),
|
||||
'formToken' => $this->c->Csrf->create($marker, $vars),
|
||||
'form' => $this->viewForm($id, $groups[$args['id']]),
|
||||
'warn' => empty($groups[$args['id']]['g_moderator']) ? null : __('Moderator info'),
|
||||
'tabindex' => 0,
|
||||
];
|
||||
$this->formAction = $this->c->Router->link($marker, $vars);
|
||||
$this->formToken = $this->c->Csrf->create($marker, $vars);
|
||||
$this->form = $this->viewForm($id, $groups[$args['id']]);
|
||||
$this->warn = empty($groups[$args['id']]['g_moderator']) ? null : __('Moderator info');
|
||||
$this->tabindex = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись данных по новой/измененной группе
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function editPost(array $args)
|
||||
|
@ -274,7 +270,7 @@ class Groups extends Admin
|
|||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
$args['_data'] = $v->getData();
|
||||
return $this->edit($args);
|
||||
}
|
||||
|
@ -334,8 +330,8 @@ class Groups extends Admin
|
|||
$this->c->Cache->delete('forums_mark');
|
||||
|
||||
return $this->c->Redirect
|
||||
->setPage('AdminGroups')
|
||||
->setMessage($id === -1 ? __('Group added redirect') : __('Group edited redirect'));
|
||||
->page('AdminGroups')
|
||||
->message($id === -1 ? __('Group added redirect') : __('Group edited redirect'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,7 +393,7 @@ class Groups extends Admin
|
|||
|
||||
$y = __('Yes');
|
||||
$n = __('No');
|
||||
if ($id !== $this->c->GROUP_GUEST && $id != $this->config['o_default_user_group']) {
|
||||
if ($id !== $this->c->GROUP_GUEST && $id != $this->c->config->o_default_user_group) {
|
||||
$form['g_moderator'] = [
|
||||
'type' => 'radio',
|
||||
'value' => isset($data['g_moderator']) ? $data['g_moderator'] : 0,
|
||||
|
|
|
@ -2,32 +2,24 @@
|
|||
|
||||
namespace ForkBB\Models\Pages\Admin;
|
||||
|
||||
use ForkBB\Models\Pages\Admin;
|
||||
|
||||
class Index extends Admin
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'admin/index';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации админки
|
||||
* @var string
|
||||
*/
|
||||
protected $adminIndex = 'index';
|
||||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->c->Lang->load('admin_index');
|
||||
$this->data = [
|
||||
'revision' => $this->config['i_fork_revision'],
|
||||
'linkStat' => $this->c->Router->link('AdminStatistics'),
|
||||
];
|
||||
$this->titles[] = __('Admin index');
|
||||
|
||||
$this->nameTpl = 'admin/index';
|
||||
$this->titles = __('Admin index');
|
||||
$this->revision = $this->c->config->i_fork_revision;
|
||||
$this->linkStat = $this->c->Router->link('AdminStatistics');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,13 @@
|
|||
|
||||
namespace ForkBB\Models\Pages\Admin;
|
||||
|
||||
use ForkBB\Models\Pages\Admin;
|
||||
|
||||
class Statistics extends Admin
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'admin/statistics';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации админки
|
||||
* @var string
|
||||
*/
|
||||
protected $adminIndex = 'index';
|
||||
|
||||
/**
|
||||
* phpinfo
|
||||
*
|
||||
* @return Page|null
|
||||
*/
|
||||
public function info()
|
||||
|
@ -33,14 +24,17 @@ class Statistics extends Admin
|
|||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function statistics()
|
||||
{
|
||||
$this->c->Lang->load('admin_index');
|
||||
$this->titles[] = __('Server statistics');
|
||||
$this->data['isAdmin'] = $this->c->user->isAdmin;
|
||||
$this->data['linkInfo'] = $this->c->Router->link('AdminInfo');
|
||||
|
||||
$this->nameTpl = 'admin/statistics';
|
||||
$this->titles = __('Server statistics');
|
||||
$this->isAdmin = $this->c->user->isAdmin;
|
||||
$this->linkInfo = $this->c->Router->link('AdminInfo');
|
||||
|
||||
// Get the server load averages (if possible)
|
||||
if (@file_exists('/proc/loadavg') && is_readable('/proc/loadavg')) {
|
||||
|
@ -57,38 +51,38 @@ class Statistics extends Admin
|
|||
}
|
||||
|
||||
$ave = @explode(' ', $ave);
|
||||
$this->data['serverLoad'] = isset($ave[2]) ? $ave[0].' '.$ave[1].' '.$ave[2] : __('Not available');
|
||||
$this->serverLoad = isset($ave[2]) ? $ave[0].' '.$ave[1].' '.$ave[2] : __('Not available');
|
||||
} elseif (!in_array(PHP_OS, array('WINNT', 'WIN32')) && preg_match('%averages?: ([\d\.]+),?\s+([\d\.]+),?\s+([\d\.]+)%i', @exec('uptime'), $ave)) {
|
||||
$this->data['serverLoad'] = $ave[1].' '.$ave[2].' '.$ave[3];
|
||||
$this->serverLoad = $ave[1].' '.$ave[2].' '.$ave[3];
|
||||
} else {
|
||||
$this->data['serverLoad'] = __('Not available');
|
||||
$this->serverLoad = __('Not available');
|
||||
}
|
||||
|
||||
// Get number of current visitors
|
||||
$this->data['numOnline'] = $this->c->DB->query('SELECT COUNT(user_id) FROM ::online WHERE idle=0')->fetchColumn();
|
||||
$this->numOnline = $this->c->DB->query('SELECT COUNT(user_id) FROM ::online WHERE idle=0')->fetchColumn();
|
||||
|
||||
$stat = $this->c->DB->statistics();
|
||||
$this->data['dbVersion'] = $stat['db'];
|
||||
$this->data['tSize'] = $this->size($stat['size']);
|
||||
$this->data['tRecords'] = $this->number($stat['records']);
|
||||
$this->dbVersion = $stat['db'];
|
||||
$this->tSize = $this->size($stat['size']);
|
||||
$this->tRecords = $this->number($stat['records']);
|
||||
unset($stat['db'], $stat['size'], $stat['records']);
|
||||
$this->data['tOther'] = $stat;
|
||||
$this->tOther = $stat;
|
||||
|
||||
// Check for the existence of various PHP opcode caches/optimizers
|
||||
if (function_exists('mmcache')) {
|
||||
$this->data['accelerator'] = '<a href="http://' . __('Turck MMCache link') . '">' . __('Turck MMCache') . '</a>';
|
||||
$this->accelerator = '<a href="http://' . __('Turck MMCache link') . '">' . __('Turck MMCache') . '</a>';
|
||||
} elseif (isset($_PHPA)) {
|
||||
$this->data['accelerator'] = '<a href="http://' . __('ionCube PHP Accelerator link') . '">' . __('ionCube PHP Accelerator') . '</a>';
|
||||
$this->accelerator = '<a href="http://' . __('ionCube PHP Accelerator link') . '">' . __('ionCube PHP Accelerator') . '</a>';
|
||||
} elseif (ini_get('apc.enabled')) {
|
||||
$this->data['accelerator'] ='<a href="http://' . __('Alternative PHP Cache (APC) link') . '">' . __('Alternative PHP Cache (APC)') . '</a>';
|
||||
$this->accelerator ='<a href="http://' . __('Alternative PHP Cache (APC) link') . '">' . __('Alternative PHP Cache (APC)') . '</a>';
|
||||
} elseif (ini_get('zend_optimizer.optimization_level')) {
|
||||
$this->data['accelerator'] = '<a href="http://' . __('Zend Optimizer link') . '">' . __('Zend Optimizer') . '</a>';
|
||||
$this->accelerator = '<a href="http://' . __('Zend Optimizer link') . '">' . __('Zend Optimizer') . '</a>';
|
||||
} elseif (ini_get('eaccelerator.enable')) {
|
||||
$this->data['accelerator'] = '<a href="http://' . __('eAccelerator link') . '">' . __('eAccelerator') . '</a>';
|
||||
$this->accelerator = '<a href="http://' . __('eAccelerator link') . '">' . __('eAccelerator') . '</a>';
|
||||
} elseif (ini_get('xcache.cacher')) {
|
||||
$this->data['accelerator'] = '<a href="http://' . __('XCache link') . '">' . __('XCache') . '</a>';
|
||||
$this->accelerator = '<a href="http://' . __('XCache link') . '">' . __('XCache') . '</a>';
|
||||
} else {
|
||||
$this->data['accelerator'] = __('NA');
|
||||
$this->accelerator = __('NA');
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
|
|
@ -4,62 +4,43 @@ namespace ForkBB\Models\Pages;
|
|||
|
||||
use ForkBB\Core\Validator;
|
||||
use ForkBB\Core\Exceptions\MailException;
|
||||
use ForkBB\Models\Page;
|
||||
use ForkBB\Models\User;
|
||||
|
||||
class Auth extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'login';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'login';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации
|
||||
* @var string
|
||||
*/
|
||||
protected $index = 'login';
|
||||
|
||||
/**
|
||||
* Для передачи User из vCheckEmail() в forgetPost()
|
||||
* @var User
|
||||
*/
|
||||
protected $tmpUser;
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots = 'noindex';
|
||||
protected $tmpUser; //????
|
||||
|
||||
/**
|
||||
* Выход пользователя
|
||||
*
|
||||
* @param array $args
|
||||
* @retrun Page
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function logout($args)
|
||||
{
|
||||
if (empty($args['token']) || ! $this->c->Csrf->verify($args['token'], 'Logout', $args)) {
|
||||
return $this->c->Redirect->setPage('Index')->setMessage(__('Bad token'));
|
||||
return $this->c->Redirect->page('Index')->message(__('Bad token'));
|
||||
}
|
||||
|
||||
$this->c->UserCookie->deleteUserCookie();
|
||||
$this->c->Cookie->deleteUser();
|
||||
$this->c->Online->delete($this->c->user);
|
||||
$this->c->UserMapper->updateLastVisit($this->c->user);
|
||||
$this->c->user->updateLastVisit();
|
||||
|
||||
$this->c->Lang->load('auth');
|
||||
return $this->c->Redirect->setPage('Index')->setMessage(__('Logout redirect'));
|
||||
return $this->c->Redirect->page('Index')->message(__('Logout redirect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для страницы входа на форум
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function login(array $args)
|
||||
|
@ -74,24 +55,25 @@ class Auth extends Page
|
|||
$args['_redirect'] = $this->c->Router->validate($args['_redirect'], 'Index');
|
||||
}
|
||||
|
||||
$this->titles[] = __('Login');
|
||||
$this->data = [
|
||||
'formAction' => $this->c->Router->link('Login'),
|
||||
'formToken' => $this->c->Csrf->create('Login'),
|
||||
'forgetLink' => $this->c->Router->link('Forget'),
|
||||
'regLink' => $this->config['o_regs_allow'] == '1'
|
||||
? $this->c->Router->link('Register')
|
||||
: null,
|
||||
'username' => $args['_username'],
|
||||
'redirect' => $args['_redirect'],
|
||||
'save' => ! empty($args['_save'])
|
||||
];
|
||||
$this->fIndex = 'login';
|
||||
$this->nameTpl = 'login';
|
||||
$this->onlinePos = 'login';
|
||||
$this->robots = 'noindex';
|
||||
$this->titles = __('Login');
|
||||
$this->formAction = $this->c->Router->link('Login');
|
||||
$this->formToken = $this->c->Csrf->create('Login');
|
||||
$this->forgetLink = $this->c->Router->link('Forget');
|
||||
$this->regLink = $this->c->config->o_regs_allow == '1' ? $this->c->Router->link('Register') : null;
|
||||
$this->username = $args['_username'];
|
||||
$this->redirect = $args['_redirect'];
|
||||
$this->save = ! empty($args['_save']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вход на форум
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function loginPost()
|
||||
|
@ -109,9 +91,9 @@ class Auth extends Page
|
|||
]);
|
||||
|
||||
if ($v->validation($_POST)) {
|
||||
return $this->c->Redirect->setUrl($v->redirect)->setMessage(__('Login redirect'));
|
||||
return $this->c->Redirect->url($v->redirect)->message(__('Login redirect'));
|
||||
} else {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
return $this->login([
|
||||
'_username' => $v->username,
|
||||
'_redirect' => $v->redirect,
|
||||
|
@ -122,27 +104,28 @@ class Auth extends Page
|
|||
|
||||
/**
|
||||
* Проверка по базе и вход на форум
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $password
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vLoginProcess(Validator $v, $password)
|
||||
{
|
||||
$error = false;
|
||||
if (! empty($v->getErrors())) {
|
||||
} elseif (! ($user = $this->c->UserMapper->getUser($v->username, 'username')) instanceof User) {
|
||||
} elseif (! ($user = $this->c->ModelUser->load($v->username, 'username')) instanceof User) {
|
||||
$error = __('Wrong user/pass');
|
||||
} elseif ($user->isUnverified) {
|
||||
$error = [__('Account is not activated'), 'w'];
|
||||
} else {
|
||||
$authorized = false;
|
||||
$hash = $user->password;
|
||||
$update = [];
|
||||
// For FluxBB by Visman 1.5.10.74 and above
|
||||
if (strlen($hash) == 40) {
|
||||
if (hash_equals($hash, sha1($password . $this->c->SALT1))) {
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$update['password'] = $hash;
|
||||
$user->password = $hash;
|
||||
$authorized = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -154,16 +137,16 @@ class Auth extends Page
|
|||
} else {
|
||||
// перезаписываем ip админа и модератора - Visman
|
||||
if ($user->isAdmMod
|
||||
&& $this->config['o_check_ip']
|
||||
&& $user->registrationIp != $this->c->user->ip
|
||||
&& $this->c->config->o_check_ip
|
||||
&& $user->registration_ip != $this->c->user->ip
|
||||
) {
|
||||
$update['registration_ip'] = $this->c->user->ip;
|
||||
$user->registration_ip = $this->c->user->ip;
|
||||
}
|
||||
// изменения юзера в базе
|
||||
$this->c->UserMapper->updateUser($user->id, $update);
|
||||
$user->update();
|
||||
|
||||
$this->c->Online->delete($this->c->user);
|
||||
$this->c->UserCookie->setUserCookie($user->id, $hash, $v->save);
|
||||
$this->c->Cookie->setUser($user);
|
||||
}
|
||||
}
|
||||
return [$password, $error];
|
||||
|
@ -171,32 +154,34 @@ class Auth extends Page
|
|||
|
||||
/**
|
||||
* Подготовка данных для страницы восстановления пароля
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function forget(array $args)
|
||||
{
|
||||
$this->nameTpl = 'passphrase_reset';
|
||||
$this->onlinePos = 'passphrase_reset';
|
||||
$this->c->Lang->load('auth');
|
||||
|
||||
if (! isset($args['_email'])) {
|
||||
$args['_email'] = '';
|
||||
}
|
||||
|
||||
$this->c->Lang->load('auth');
|
||||
|
||||
$this->titles[] = __('Passphrase reset');
|
||||
$this->data = [
|
||||
'formAction' => $this->c->Router->link('Forget'),
|
||||
'formToken' => $this->c->Csrf->create('Forget'),
|
||||
'email' => $args['_email'],
|
||||
];
|
||||
$this->fIndex = 'login';
|
||||
$this->nameTpl = 'passphrase_reset';
|
||||
$this->onlinePos = 'passphrase_reset';
|
||||
$this->robots = 'noindex';
|
||||
$this->titles = __('Passphrase reset');
|
||||
$this->formAction = $this->c->Router->link('Forget');
|
||||
$this->formToken = $this->c->Csrf->create('Forget');
|
||||
$this->email = $args['_email'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправка письма для восстановления пароля
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function forgetPost()
|
||||
|
@ -213,7 +198,7 @@ class Auth extends Page
|
|||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
return $this->forget([
|
||||
'_email' => $v->email,
|
||||
]);
|
||||
|
@ -224,7 +209,7 @@ class Auth extends Page
|
|||
$link = $this->c->Router->link('ChangePassword', ['email' => $v->email, 'key' => $key, 'hash' => $hash]);
|
||||
$tplData = [
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
'fMailer' => __('Mailer', $this->config['o_board_title']),
|
||||
'fMailer' => __('Mailer', $this->c->config->o_board_title),
|
||||
'username' => $this->tmpUser->username,
|
||||
'link' => $link,
|
||||
];
|
||||
|
@ -235,7 +220,7 @@ class Auth extends Page
|
|||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->tmpUser->language)
|
||||
->setTo($v->email, $this->tmpUser->username)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setFrom($this->c->config->o_webmaster_email, __('Mailer', $this->c->config->o_board_title))
|
||||
->setTpl('passphrase_reset.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
|
@ -243,33 +228,42 @@ class Auth extends Page
|
|||
}
|
||||
|
||||
if ($isSent) {
|
||||
$this->c->UserMapper->updateUser($this->tmpUser->id, ['activate_string' => $key, 'last_email_sent' => time()]);
|
||||
return $this->c->Message->message(__('Forget mail', $this->config['o_admin_email']), false, 200);
|
||||
$this->tmpUser->activate_string = $key;
|
||||
$this->tmpUser->last_email_sent = time();
|
||||
$this->tmpUser->update();
|
||||
return $this->c->Message->message(__('Forget mail', $this->c->config->o_admin_email), false, 200);
|
||||
} else {
|
||||
return $this->c->Message->message(__('Error mail', $this->config['o_admin_email']), true, 200);
|
||||
return $this->c->Message->message(__('Error mail', $this->c->config->o_admin_email), true, 200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка email
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $username
|
||||
* @param string $email
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vCheckEmail(Validator $v, $email)
|
||||
{
|
||||
$error = false;
|
||||
// есть ошибки
|
||||
if (! empty($v->getErrors())) {
|
||||
return [$email, false];
|
||||
}
|
||||
|
||||
$error = false;
|
||||
$user = $this->c->ModelUser;
|
||||
$user->__email = $email;
|
||||
|
||||
// email забанен
|
||||
} elseif ($this->c->CheckBans->isBanned(null, $email) > 0) {
|
||||
if ($this->c->bans->isBanned($user) > 0) {
|
||||
$error = __('Banned email');
|
||||
// нет пользователя с таким email
|
||||
} elseif (! ($user = $this->c->UserMapper->getUser($email, 'email')) instanceof User) {
|
||||
} elseif (! $user->load($email, 'email') instanceof User) {
|
||||
$error = __('Invalid email');
|
||||
// за последний час уже был запрос на этот email
|
||||
} elseif (! empty($user->lastEmailSent) && time() - $user->lastEmailSent < 3600) {
|
||||
$error = [__('Email flood', (int) (($user->lastEmailSent + 3600 - time()) / 60)), 'e'];
|
||||
} elseif (! empty($user->last_email_sent) && time() - $user->last_email_sent < 3600) {
|
||||
$error = [__('Email flood', (int) (($user->last_email_sent + 3600 - time()) / 60)), 'e'];
|
||||
} else {
|
||||
$this->tmpUser = $user;
|
||||
}
|
||||
|
@ -278,23 +272,23 @@ class Auth extends Page
|
|||
|
||||
/**
|
||||
* Подготовка данных для формы изменения пароля
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function changePass(array $args)
|
||||
{
|
||||
$this->nameTpl = 'change_passphrase';
|
||||
$this->onlinePos = 'change_passphrase';
|
||||
|
||||
if (isset($args['_ok'])) {
|
||||
unset($args['_ok']);
|
||||
if (isset($args['_user'])) {
|
||||
$user = $args['_user'];
|
||||
unset($args['_user']);
|
||||
} else {
|
||||
// что-то пошло не так
|
||||
if (! hash_equals($args['hash'], $this->c->Secury->hash($args['email'] . $args['key']))
|
||||
|| ! ($user = $this->c->UserMapper->getUser($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activateString)
|
||||
|| $user->activateString{0} !== 'p'
|
||||
|| ! hash_equals($user->activateString, $args['key'])
|
||||
|| ! ($user = $this->c->ModelUser->load($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activate_string)
|
||||
|| $user->activate_string{0} !== 'p'
|
||||
|| ! hash_equals($user->activate_string, $args['key'])
|
||||
) {
|
||||
return $this->c->Message->message(__('Bad request'), false);
|
||||
}
|
||||
|
@ -303,33 +297,39 @@ class Auth extends Page
|
|||
$this->c->Lang->load('auth');
|
||||
|
||||
if ($user->isUnverified) {
|
||||
$this->c->UserMapper->updateUser($user->id, ['group_id' => $this->config['o_default_user_group'], 'email_confirmed' => 1]);
|
||||
$user->group_id = $this->c->config->o_default_user_group;
|
||||
$user->email_confirmed = 1;
|
||||
$user->update();
|
||||
$this->c->{'users_info update'};
|
||||
$this->iswev['i'][] = __('Account activated');
|
||||
$this->a['fIswev']['i'][] = __('Account activated');
|
||||
}
|
||||
|
||||
$this->titles[] = __('Change pass');
|
||||
$this->data = [
|
||||
'formAction' => $this->c->Router->link('ChangePassword', $args),
|
||||
'formToken' => $this->c->Csrf->create('ChangePassword', $args),
|
||||
];
|
||||
$this->fIndex = 'login';
|
||||
$this->nameTpl = 'change_passphrase';
|
||||
$this->onlinePos = 'change_passphrase';
|
||||
$this->robots = 'noindex';
|
||||
$this->titles = __('Passphrase reset');
|
||||
$this->formAction = $this->c->Router->link('ChangePassword', $args);
|
||||
$this->formToken = $this->c->Csrf->create('ChangePassword', $args);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Смена пароля
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function changePassPost(array $args)
|
||||
{
|
||||
// что-то пошло не так
|
||||
if (! hash_equals($args['hash'], $this->c->Secury->hash($args['email'] . $args['key']))
|
||||
|| ! ($user = $this->c->UserMapper->getUser($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activateString)
|
||||
|| $user->activateString{0} !== 'p'
|
||||
|| ! hash_equals($user->activateString, $args['key'])
|
||||
|| ! ($user = $this->c->ModelUser->load($args['email'], 'email')) instanceof User
|
||||
|| empty($user->activate_string)
|
||||
|| $user->activate_string{0} !== 'p'
|
||||
|| ! hash_equals($user->activate_string, $args['key'])
|
||||
) {
|
||||
return $this->c->Message->message(__('Bad request'), false);
|
||||
}
|
||||
|
@ -349,15 +349,18 @@ class Auth extends Page
|
|||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$this->iswev = $v->getErrors();
|
||||
$args['_ok'] = true;
|
||||
$this->fIswev = $v->getErrors();
|
||||
$args['_user'] = $user;
|
||||
return $this->changePass($args);
|
||||
}
|
||||
$data = $v->getData();
|
||||
|
||||
$this->c->UserMapper->updateUser($user->id, ['password' => password_hash($data['password'], PASSWORD_DEFAULT), 'email_confirmed' => 1, 'activate_string' => null]);
|
||||
$user->password = password_hash($data['password'], PASSWORD_DEFAULT);
|
||||
$user->email_confirmed = 1;
|
||||
$user->activate_string = null;
|
||||
$user->update();
|
||||
|
||||
$this->iswev['s'][] = __('Pass updated');
|
||||
$this->a['fIswev']['s'][] = __('Pass updated');
|
||||
return $this->login(['_redirect' => $this->c->Router->link('Index')]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,42 +2,41 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
use ForkBB\Models\User;
|
||||
|
||||
class Ban extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'ban';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'ban';
|
||||
|
||||
/**
|
||||
* HTTP статус ответа для данной страницы
|
||||
* @var int
|
||||
*/
|
||||
protected $httpStatus = 403;
|
||||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
* @param array $banned
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function ban(array $banned)
|
||||
public function ban(User $user)
|
||||
{
|
||||
$this->titles[] = __('Info');
|
||||
$ban = $user->banInfo;
|
||||
|
||||
if (! empty($banned['expire'])) {
|
||||
$banned['expire'] = strtolower($this->time($banned['expire'], true));
|
||||
if (! empty($ban['expire'])) {
|
||||
$ban['expire'] = strtolower($this->time($ban['expire'], true));
|
||||
}
|
||||
$this->data = [
|
||||
'banned' => $banned,
|
||||
'adminEmail' => $this->config['o_admin_email'],
|
||||
];
|
||||
|
||||
$this->httpStatus = 403;
|
||||
$this->nameTpl = 'ban';
|
||||
# $this->onlinePos = 'ban';
|
||||
# $this->robots = 'noindex';
|
||||
$this->titles = __('Info');
|
||||
$this->ban = $ban;
|
||||
$this->adminEmail = $this->c->config->o_admin_email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function prepare()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,22 +6,44 @@ trait CrumbTrait
|
|||
{
|
||||
/**
|
||||
* Возвращает массив хлебных крошек
|
||||
*
|
||||
* @param mixed $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCrumbs(...$args)
|
||||
protected function crumbs(...$args)
|
||||
{
|
||||
$crumbs = [];
|
||||
$active = true;
|
||||
|
||||
foreach ($args as $arg) {
|
||||
if (isset($arg->forum_name)) {
|
||||
while ($arg->id > 0) {
|
||||
$this->titles = $arg->forum_name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $arg->id, 'name' => $arg->forum_name]),
|
||||
$arg->forum_name,
|
||||
$active,
|
||||
];
|
||||
$active = null;
|
||||
$arg = $arg->parent;
|
||||
}
|
||||
} else {
|
||||
$this->titles = (string) $arg;
|
||||
$crumbs[] = [
|
||||
null,
|
||||
(string) $arg,
|
||||
$active,
|
||||
];
|
||||
}
|
||||
/*
|
||||
if (is_array($arg)) {
|
||||
$cur = array_shift($arg);
|
||||
// массив разделов
|
||||
if (is_array($cur)) {
|
||||
$id = $arg[0];
|
||||
while (true) {
|
||||
$this->titles[] = $cur[$id]['forum_name'];
|
||||
$this->titles = $cur[$id]['forum_name'];
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $id, 'name' => $cur[$id]['forum_name']]),
|
||||
$cur[$id]['forum_name'],
|
||||
|
@ -48,7 +70,7 @@ trait CrumbTrait
|
|||
} else {
|
||||
continue;
|
||||
}
|
||||
$this->titles[] = $name;
|
||||
$this->titles = $name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link($cur, $vars),
|
||||
$name,
|
||||
|
@ -57,13 +79,14 @@ trait CrumbTrait
|
|||
}
|
||||
// предположительно идет только название, без ссылки
|
||||
} else {
|
||||
$this->titles[] = (string) $arg;
|
||||
$this->titles = (string) $arg;
|
||||
$crumbs[] = [
|
||||
null,
|
||||
(string) $arg,
|
||||
$active,
|
||||
];
|
||||
}
|
||||
*/
|
||||
$active = null;
|
||||
}
|
||||
// главная страница
|
||||
|
|
|
@ -2,36 +2,20 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Debug extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'layouts/debug';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = null;
|
||||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function debug()
|
||||
{
|
||||
$this->data = [
|
||||
'time' => $this->number(microtime(true) - $this->c->START, 3),
|
||||
'numQueries' => $this->c->DB->getCount(),
|
||||
'memory' => $this->size(memory_get_usage()),
|
||||
'peak' => $this->size(memory_get_peak_usage()),
|
||||
];
|
||||
|
||||
if ($this->c->DEBUG > 1) {
|
||||
$total = 0;
|
||||
$this->data['queries'] = array_map(
|
||||
$this->queries = array_map(
|
||||
function($a) use (&$total) {
|
||||
$total += $a[1];
|
||||
$a[1] = $this->number($a[1], 3);
|
||||
|
@ -39,29 +23,36 @@ class Debug extends Page
|
|||
},
|
||||
$this->c->DB->getQueries()
|
||||
);
|
||||
$this->data['total'] = $this->number($total, 3);
|
||||
$this->total = $this->number($total, 3);
|
||||
} else {
|
||||
$this->data['queries'] = null;
|
||||
$this->queries = null;
|
||||
}
|
||||
|
||||
$this->nameTpl = 'layouts/debug';
|
||||
$this->onlinePos = null;
|
||||
$this->numQueries = $this->c->DB->getCount();
|
||||
$this->memory = $this->size(memory_get_usage());
|
||||
$this->peak = $this->size(memory_get_peak_usage());
|
||||
$this->time = $this->number(microtime(true) - $this->c->START, 3);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает HTTP заголовки страницы
|
||||
* @return array
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function httpHeaders()
|
||||
public function prepare()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* Возвращает HTTP заголовки страницы
|
||||
* $this->httpHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
protected function getHttpHeaders()
|
||||
{
|
||||
return $this->data;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,13 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Forum extends Page
|
||||
{
|
||||
use ForumsTrait;
|
||||
use CrumbTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'forum';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'forum';
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
|
@ -29,41 +19,19 @@ class Forum extends Page
|
|||
$this->c->Lang->load('forum');
|
||||
$this->c->Lang->load('subforums');
|
||||
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
// раздел отсутствует в доступных
|
||||
if (empty($fDesc[$args['id']])) {
|
||||
$forum = $this->c->forums->loadTree($args['id']);
|
||||
if (empty($forum)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$parent = isset($fDesc[$args['id']][0]) ? $fDesc[$args['id']][0] : 0;
|
||||
$perm = $fTree[$parent][$args['id']];
|
||||
|
||||
// редирект, если раздел это ссылка
|
||||
if (! empty($perm['redirect_url'])) {
|
||||
return $this->c->Redirect->setUrl($perm['redirect_url']);
|
||||
if (! empty($forum->redirect_url)) {
|
||||
return $this->c->Redirect->url($forum->redirect_url);
|
||||
}
|
||||
|
||||
$user = $this->c->user;
|
||||
$vars = [
|
||||
':fid' => $args['id'],
|
||||
':uid' => $user->id,
|
||||
':gid' => $user->groupId,
|
||||
];
|
||||
if ($user->isGuest) {
|
||||
$sql = 'SELECT f.moderators, f.num_topics, f.sort_by, 0 AS is_subscribed FROM ::forums AS f WHERE f.id=?i:fid';
|
||||
} else {
|
||||
$sql = 'SELECT f.moderators, f.num_topics, f.sort_by, s.user_id AS is_subscribed, mof.mf_mark_all_read FROM ::forums AS f LEFT JOIN ::forum_subscriptions AS s ON (f.id=s.forum_id AND s.user_id=?i:uid) LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND f.id=mof.fid) WHERE f.id=?i:fid';
|
||||
}
|
||||
$curForum = $this->c->DB->query($sql, $vars)->fetch();
|
||||
|
||||
// нет данных по данному разделу
|
||||
if (empty($curForum)) {
|
||||
return $this->c->Message->message('Bad request'); //???? может в лог ошибок?
|
||||
}
|
||||
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
if (empty($curForum['num_topics'])) {
|
||||
if (empty($forum->num_topics)) {
|
||||
// попытка открыть страницу которой нет
|
||||
if ($page !== 1) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
|
@ -73,16 +41,16 @@ class Forum extends Page
|
|||
$offset = 0;
|
||||
$topics = null;
|
||||
} else {
|
||||
$pages = ceil($curForum['num_topics'] / $user->dispTopics);
|
||||
$pages = ceil($forum->num_topics / $user->disp_topics);
|
||||
|
||||
// попытка открыть страницу которой нет
|
||||
if ($page < 1 || $page > $pages) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $user->dispTopics;
|
||||
$offset = ($page - 1) * $user->disp_topics;
|
||||
|
||||
switch ($curForum['sort_by']) {
|
||||
switch ($forum->sort_by) {
|
||||
case 1:
|
||||
$sortBy = 'posted DESC';
|
||||
break;
|
||||
|
@ -96,9 +64,9 @@ class Forum extends Page
|
|||
}
|
||||
|
||||
$vars = [
|
||||
':fid' => $args['id'],
|
||||
':fid' => $args['id'],
|
||||
':offset' => $offset,
|
||||
':rows' => $user->dispTopics,
|
||||
':rows' => $user->disp_topics,
|
||||
];
|
||||
$topics = $this->c->DB
|
||||
->query("SELECT id FROM ::topics WHERE forum_id=?i:fid ORDER BY sticky DESC, {$sortBy}, id DESC LIMIT ?i:offset, ?i:rows", $vars)
|
||||
|
@ -107,11 +75,11 @@ class Forum extends Page
|
|||
|
||||
if (! empty($topics)) {
|
||||
$vars = [
|
||||
':uid' => $user->id,
|
||||
':uid' => $user->id,
|
||||
':topics' => $topics,
|
||||
];
|
||||
|
||||
if (! $user->isGuest && $this->config['o_show_dot'] == '1') {
|
||||
if (! $user->isGuest && $this->c->config->o_show_dot == '1') {
|
||||
$dots = $this->c->DB
|
||||
->query('SELECT topic_id FROM ::posts WHERE poster_id=?i:uid AND topic_id IN (?ai:topics) GROUP BY topic_id', $vars)
|
||||
->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
@ -121,8 +89,8 @@ class Forum extends Page
|
|||
}
|
||||
|
||||
if (! $user->isGuest) {
|
||||
$lower = max((int) $user->uMarkAllRead, (int) $curForum['mf_mark_all_read']);
|
||||
$upper = max($lower, (int) $user->lastVisit);
|
||||
$lower = max((int) $user->u_mark_all_read, (int) $forum->mf_mark_all_read);
|
||||
$upper = max($lower, (int) $user->last_visit);
|
||||
}
|
||||
|
||||
if ($user->isGuest) {
|
||||
|
@ -133,7 +101,7 @@ class Forum extends Page
|
|||
$topics = $this->c->DB->query($sql, $vars)->fetchAll();
|
||||
|
||||
foreach ($topics as &$cur) {
|
||||
$cur['subject'] = $this->censor($cur['subject']);
|
||||
$cur['subject'] = $this->c->censorship->censor($cur['subject']);
|
||||
// перенос темы
|
||||
if ($cur['moved_to']) {
|
||||
$cur['link'] = $this->c->Router->link('Topic', ['id' => $cur['moved_to'], 'name' => $cur['subject']]);
|
||||
|
@ -144,7 +112,7 @@ class Forum extends Page
|
|||
continue;
|
||||
}
|
||||
// страницы темы
|
||||
$tPages = ceil(($cur['num_replies'] + 1) / $user->dispPosts);
|
||||
$tPages = ceil(($cur['num_replies'] + 1) / $user->disp_posts);
|
||||
if ($tPages > 1) {
|
||||
$cur['pages'] = $this->c->Func->paginate($tPages, -1, 'Topic', ['id' => $cur['id'], 'name' => $cur['subject']]);
|
||||
} else {
|
||||
|
@ -153,7 +121,7 @@ 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['views'] = $this->config['o_topic_views'] == '1' ? $this->number($cur['num_views']) : null;
|
||||
$cur['views'] = $this->c->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']);
|
||||
|
@ -182,24 +150,22 @@ class Forum extends Page
|
|||
unset($cur);
|
||||
}
|
||||
|
||||
$moders = empty($curForum['moderators']) ? [] : array_flip(unserialize($curForum['moderators']));
|
||||
$newOn = $perm['post_topics'] == 1
|
||||
|| (null === $perm['post_topics'] && $user->gPostTopics == 1)
|
||||
$moders = empty($forum->moderators) ? [] : array_flip(unserialize($forum->moderators));
|
||||
$newOn = $forum->post_topics == 1
|
||||
|| (null === $forum->post_topics && $user->g_post_topics == 1)
|
||||
|| $user->isAdmin
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]));
|
||||
|
||||
$this->onlinePos = 'forum-' . $args['id'];
|
||||
|
||||
$this->data = [
|
||||
'forums' => $this->getForumsData($args['id']),
|
||||
'topics' => $topics,
|
||||
'crumbs' => $this->getCrumbs([$fDesc, $args['id']]),
|
||||
'forumName' => $fDesc[$args['id']]['forum_name'],
|
||||
'newTopic' => $newOn ? $this->c->Router->link('NewTopic', ['id' => $args['id']]) : null,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, '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]);
|
||||
$this->fIndex = 'index';
|
||||
$this->nameTpl = 'forum';
|
||||
$this->onlinePos = 'forum-' . $args['id'];
|
||||
$this->canonical = $this->c->Router->link('Forum', ['id' => $args['id'], 'name' => $forum->forum_name, 'page' => $page]);
|
||||
$this->forums = $this->forumsData($args['id']);
|
||||
$this->topics = $topics;
|
||||
$this->crumbs = $this->crumbs($forum);
|
||||
$this->forumName = $forum->forum_name;
|
||||
$this->newTopic = $newOn ? $this->c->Router->link('NewTopic', ['id' => $args['id']]) : null;
|
||||
$this->pages = $this->c->Func->paginate($pages, $page, 'Forum', ['id' => $args['id'], 'name' => $forum->forum_name]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -6,88 +6,29 @@ trait ForumsTrait
|
|||
{
|
||||
/**
|
||||
* Получение данных по разделам
|
||||
* @param int $parent
|
||||
*
|
||||
* @param int $rootId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getForumsData($parent = 0)
|
||||
protected function forumsData($rootId = 0)
|
||||
{
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
// раздел $parent не имеет подразделов для вывода или они не доступны
|
||||
if (empty($fTree[$parent])) {
|
||||
$root = $this->c->forums->loadTree($rootId);
|
||||
if (empty($root)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$user = $this->c->user;
|
||||
|
||||
// текущие данные по подразделам
|
||||
$vars = [
|
||||
':id' => $user->id,
|
||||
':forums' => array_slice($fAsc[$parent], 1),
|
||||
];
|
||||
if ($user->isGuest) {
|
||||
$stmt = $this->c->DB->query('SELECT id, forum_desc, moderators, num_topics, num_posts, last_post, last_post_id, last_poster, last_topic FROM ::forums WHERE id IN (?ai:forums)', $vars);
|
||||
} else {
|
||||
$stmt = $this->c->DB->query('SELECT f.id, f.forum_desc, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, f.last_topic, mof.mf_mark_all_read FROM ::forums AS f LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:id AND f.id=mof.fid) WHERE f.id IN (?ai:forums)', $vars);
|
||||
}
|
||||
$forums = [];
|
||||
while ($cur = $stmt->fetch()) {
|
||||
$forums[$cur['id']] = $cur;
|
||||
}
|
||||
|
||||
// поиск новых
|
||||
$new = [];
|
||||
if (! $user->isGuest) {
|
||||
// предварительная проверка разделов
|
||||
$max = max((int) $user->lastVisit, (int) $user->uMarkAllRead);
|
||||
foreach ($forums as $id => $cur) {
|
||||
$t = max($max, (int) $cur['mf_mark_all_read']);
|
||||
if ($cur['last_post'] > $t) {
|
||||
$new[$id] = $t;
|
||||
}
|
||||
}
|
||||
// проверка по темам
|
||||
if (! empty($new)) {
|
||||
$vars = [
|
||||
':id' => $user->id,
|
||||
':forums' => array_keys($new),
|
||||
':max' => $max,
|
||||
];
|
||||
$stmt = $this->c->DB->query('SELECT t.forum_id, t.last_post FROM ::topics AS t LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:id AND mot.tid=t.id) WHERE t.forum_id IN(?ai:forums) AND t.last_post>?i:max AND t.moved_to IS NULL AND (mot.mt_last_visit IS NULL OR t.last_post>mot.mt_last_visit)', $vars);
|
||||
$tmp = [];
|
||||
while ($cur = $stmt->fetch()) {
|
||||
if ($cur['last_post'] > $new[$cur['forum_id']]) {
|
||||
$tmp[$cur['forum_id']] = true;
|
||||
}
|
||||
}
|
||||
$new = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
$r = $this->c->Router;
|
||||
|
||||
// формированием таблицы разделов
|
||||
$result = [];
|
||||
foreach ($fTree[$parent] as $fId => $cur) {
|
||||
// список подразделов
|
||||
$subForums = [];
|
||||
if (isset($fTree[$fId])) {
|
||||
foreach ($fTree[$fId] as $f) {
|
||||
$subForums[] = [
|
||||
$r->link('Forum', [
|
||||
'id' => $f['fid'],
|
||||
'name' => $f['forum_name']
|
||||
]),
|
||||
$f['forum_name']
|
||||
];
|
||||
}
|
||||
}
|
||||
foreach ($root->subforums as $forumId => $forum) {
|
||||
// модераторы
|
||||
$moderators = [];
|
||||
if (!empty($forums[$fId]['moderators'])) {
|
||||
$mods = unserialize($forums[$fId]['moderators']);
|
||||
if (! empty($forum->moderators)) {
|
||||
$mods = unserialize($forum->moderators);
|
||||
foreach ($mods as $name => $id) {
|
||||
if ($user->gViewUsers == '1') {
|
||||
if ($this->c->user->g_view_users == '1') {
|
||||
$moderators[] = [
|
||||
$r->link('User', [
|
||||
'id' => $id,
|
||||
|
@ -100,36 +41,49 @@ trait ForumsTrait
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// список подразделов
|
||||
$subForums = [];
|
||||
foreach ($forum->subforums as $subId => $subforum) {
|
||||
$subForums[] = [
|
||||
$r->link('Forum', [
|
||||
'id' => $subId,
|
||||
'name' => $subforum->forum_name,
|
||||
]),
|
||||
$subforum->forum_name,
|
||||
];
|
||||
}
|
||||
|
||||
// статистика по разделам
|
||||
$numT = 0;
|
||||
$numP = 0;
|
||||
$time = 0;
|
||||
$postId = 0;
|
||||
$poster = '';
|
||||
$topic = '';
|
||||
$fnew = false;
|
||||
foreach ($fAsc[$fId] as $id) {
|
||||
$fnew = $fnew || isset($new[$id]);
|
||||
$numT += $forums[$id]['num_topics'];
|
||||
$numP += $forums[$id]['num_posts'];
|
||||
if ($forums[$id]['last_post'] > $time) {
|
||||
$time = $forums[$id]['last_post'];
|
||||
$postId = $forums[$id]['last_post_id'];
|
||||
$poster = $forums[$id]['last_poster'];
|
||||
$topic = $forums[$id]['last_topic'];
|
||||
$numT = (int) $forum->num_topics;
|
||||
$numP = (int) $forum->num_posts;
|
||||
$time = (int) $forum->last_post;
|
||||
$postId = (int) $forum->last_post_id;
|
||||
$poster = $forum->last_poster;
|
||||
$topic = $forum->last_topic;
|
||||
$fnew = $forum->newMessages;
|
||||
foreach ($forum->descendants as $chId => $children) {
|
||||
$fnew = $fnew || $children->newMessages;
|
||||
$numT += $children->num_topics;
|
||||
$numP += $children->num_posts;
|
||||
if ($children->last_post > $time) {
|
||||
$time = $children->last_post;
|
||||
$postId = $children->last_post_id;
|
||||
$poster = $children->last_poster;
|
||||
$topic = $children->last_topic;
|
||||
}
|
||||
}
|
||||
|
||||
$result[$cur['cid']]['name'] = $cur['cat_name'];
|
||||
$result[$cur['cid']]['forums'][] = [
|
||||
'fid' => $fId,
|
||||
'forum_name' => $cur['forum_name'],
|
||||
'forum_desc' => $forums[$fId]['forum_desc'],
|
||||
$result[$forum->cid]['name'] = $forum->cat_name;
|
||||
$result[$forum->cid]['forums'][] = [
|
||||
'fid' => $forumId,
|
||||
'forum_name' => $forum->forum_name,
|
||||
'forum_desc' => $forum->forum_desc,
|
||||
'forum_link' => $r->link('Forum', [
|
||||
'id' => $fId,
|
||||
'name' => $cur['forum_name']
|
||||
'id' => $forumId,
|
||||
'name' => $forum->forum_name,
|
||||
]),
|
||||
'redirect_url' => $cur['redirect_url'],
|
||||
'redirect_url' => $forum->redirect_url,
|
||||
'subforums' => $subForums,
|
||||
'moderators' => $moderators,
|
||||
'num_topics' => $numT,
|
||||
|
@ -139,7 +93,7 @@ trait ForumsTrait
|
|||
'last_post' => $this->time($time),
|
||||
'last_post_id' => $postId > 0 ? $r->link('ViewPost', ['id' => $postId]) : null,
|
||||
'last_poster' => $poster,
|
||||
'last_topic' => $topic,
|
||||
'last_topic' => $this->c->censorship->censor($topic),
|
||||
'new' => $fnew,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -2,39 +2,16 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Index extends Page
|
||||
{
|
||||
use ForumsTrait;
|
||||
use OnlineTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'index';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'index';
|
||||
|
||||
/**
|
||||
* Тип обработки пользователей онлайн
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineType = true;
|
||||
|
||||
/**
|
||||
* Тип возврата данных при onlineType === true
|
||||
* Если true, то из online должны вернутся только пользователи находящиеся на этой же странице
|
||||
* Если false, то все пользователи online
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineFilter = false;
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function view()
|
||||
|
@ -42,29 +19,31 @@ class Index extends Page
|
|||
$this->c->Lang->load('index');
|
||||
$this->c->Lang->load('subforums');
|
||||
|
||||
$stats = $this->c->users_info;
|
||||
$stats = [];
|
||||
$stats['total_users'] = $this->number($this->c->stats->userTotal);
|
||||
$stats['total_posts'] = $this->number($this->c->stats->postTotal);
|
||||
$stats['total_topics'] = $this->number($this->c->stats->topicTotal);
|
||||
|
||||
$stmt = $this->c->DB->query('SELECT SUM(num_topics), SUM(num_posts) FROM ::forums');
|
||||
list($stats['total_topics'], $stats['total_posts']) = array_map([$this, 'number'], array_map('intval', $stmt->fetch(\PDO::FETCH_NUM)));
|
||||
|
||||
$stats['total_users'] = $this->number($stats['total_users']);
|
||||
|
||||
if ($this->c->user->gViewUsers == '1') {
|
||||
if ($this->c->user->g_view_users == '1') {
|
||||
$stats['newest_user'] = [
|
||||
$this->c->Router->link('User', [
|
||||
'id' => $stats['last_user']['id'],
|
||||
'name' => $stats['last_user']['username'],
|
||||
'id' => $this->c->stats->userLast['id'],
|
||||
'name' => $this->c->stats->userLast['username'],
|
||||
]),
|
||||
$stats['last_user']['username']
|
||||
$this->c->stats->userLast['username']
|
||||
];
|
||||
} else {
|
||||
$stats['newest_user'] = $stats['last_user']['username'];
|
||||
$stats['newest_user'] = $this->c->stats->userLast['username'];
|
||||
}
|
||||
$this->data['stats'] = $stats;
|
||||
$this->data['online'] = $this->getUsersOnlineInfo();
|
||||
$this->data['forums'] = $this->getForumsData();
|
||||
|
||||
$this->canonical = $this->c->Router->link('Index');
|
||||
$this->nameTpl = 'index';
|
||||
$this->onlinePos = 'index';
|
||||
$this->onlineType = true;
|
||||
$this->onlineFilter = false;
|
||||
$this->canonical = $this->c->Router->link('Index');
|
||||
$this->stats = $stats;
|
||||
$this->online = $this->usersOnlineInfo();
|
||||
$this->forums = $this->forumsData();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -4,29 +4,14 @@ namespace ForkBB\Models\Pages;
|
|||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Core\Validator;
|
||||
use ForkBB\Models\Page;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use RuntimeException;
|
||||
|
||||
class Install extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'layouts/install';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = null;
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots = 'noindex';
|
||||
const PHP_MIN = '5.6.0';
|
||||
|
||||
/**
|
||||
* Для MySQL
|
||||
|
@ -36,33 +21,30 @@ class Install extends Page
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
$container->Lang->load('common', $this->config['o_default_lang']);
|
||||
$container->Lang->load('common', $container->config->o_default_lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* @return array
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function getData()
|
||||
public function prepare()
|
||||
{
|
||||
return $this->data + [
|
||||
'pageHeads' => $this->pageHeads(),
|
||||
'fIswev' => $this->getIswev(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возращает типы БД поддерживаемые PDO
|
||||
*
|
||||
* @param string $curType
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDBTypes($curType = null)
|
||||
protected function DBTypes($curType = null)
|
||||
{
|
||||
$dbTypes = [];
|
||||
$pdoDrivers = PDO::getAvailableDrivers();
|
||||
|
@ -93,15 +75,47 @@ class Install extends Page
|
|||
|
||||
/**
|
||||
* Подготовка данных для страницы установки форума
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function install(array $args)
|
||||
{
|
||||
$this->nameTpl = 'layouts/install';
|
||||
$this->onlinePos = null;
|
||||
$this->robots = 'noindex';
|
||||
$this->rev = $this->c->FORK_REVISION;
|
||||
$this->formAction = $this->c->Router->link('Install');
|
||||
|
||||
// версия PHP
|
||||
if (version_compare(PHP_VERSION, self::PHP_MIN, '<')) {
|
||||
$this->a['fIswev']['e'][] = __('You are running error', 'PHP', PHP_VERSION, $this->c->FORK_REVISION, self::PHP_MIN);
|
||||
}
|
||||
|
||||
// доступность папок на запись
|
||||
$folders = [
|
||||
$this->c->DIR_CONFIG,
|
||||
$this->c->DIR_CACHE,
|
||||
$this->c->DIR_PUBLIC . '/avatar',
|
||||
];
|
||||
foreach ($folders as $folder) {
|
||||
if (! is_writable($folder)) {
|
||||
$this->a['fIswev']['e'][] = __('Alert folder', $folder);
|
||||
}
|
||||
}
|
||||
|
||||
// доступность шаблона конфигурации
|
||||
$config = file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
|
||||
if (false === $config) {
|
||||
$this->a['fIswev']['e'][] = __('No access to main.dist.php');
|
||||
}
|
||||
unset($config);
|
||||
|
||||
// язык
|
||||
$langs = $this->c->Func->getLangs();
|
||||
if (empty($langs)) {
|
||||
$this->iswev['e'][] = 'No language pack.';
|
||||
$this->a['fIswev']['e'][] = 'No language pack.';
|
||||
$installLang = $installLangs = $defaultLangs = 'English';
|
||||
} else {
|
||||
if (isset($args['installlang'])) {
|
||||
|
@ -123,27 +137,14 @@ class Install extends Page
|
|||
}
|
||||
|
||||
}
|
||||
unset($args['installlang']);
|
||||
// версия PHP
|
||||
$phpMin = '5.6.0';
|
||||
if (version_compare(PHP_VERSION, $phpMin, '<')) {
|
||||
$this->iswev['e'][] = __('You are running error', 'PHP', PHP_VERSION, $this->c->FORK_REVISION, $phpMin);
|
||||
}
|
||||
// доступность папок на запись
|
||||
$folders = [
|
||||
$this->c->DIR_CONFIG,
|
||||
$this->c->DIR_CACHE,
|
||||
$this->c->DIR_PUBLIC . '/avatar',
|
||||
];
|
||||
foreach ($folders as $folder) {
|
||||
if (! is_writable($folder)) {
|
||||
$this->iswev['e'][] = __('Alert folder', $folder);
|
||||
}
|
||||
}
|
||||
$this->installLangs = $installLangs;
|
||||
$this->installLang = $installLang;
|
||||
$this->defaultLangs = $defaultLangs;
|
||||
|
||||
// стиль
|
||||
$styles = $this->c->Func->getStyles();
|
||||
if (empty($styles)) {
|
||||
$this->iswev['e'][] = __('No styles');
|
||||
$this->a['fIswev']['e'][] = __('No styles');
|
||||
$defaultStyles = ['ForkBB'];
|
||||
} else {
|
||||
$defaultStyles = [];
|
||||
|
@ -152,43 +153,46 @@ class Install extends Page
|
|||
$defaultStyles[] = $style == $defStyle ? [$style, 1] : [$style];
|
||||
}
|
||||
}
|
||||
unset($args['defaultstyle']);
|
||||
// типы БД
|
||||
$dbTypes = $this->getDBTypes(isset($args['dbtype']) ? $args['dbtype'] : null);
|
||||
if (empty($dbTypes)) {
|
||||
$this->iswev['e'][] = __('No DB extensions');
|
||||
}
|
||||
unset($args['dbtype']);
|
||||
// доступность шаблона конфигурации
|
||||
$config = file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
|
||||
if (false === $config) {
|
||||
$this->iswev['e'][] = __('No access to main.dist.php');
|
||||
}
|
||||
unset($config);
|
||||
$this->defaultStyles = $defaultStyles;
|
||||
|
||||
// типы БД
|
||||
$dbTypes = $this->DBTypes(isset($args['dbtype']) ? $args['dbtype'] : null);
|
||||
if (empty($dbTypes)) {
|
||||
$this->a['fIswev']['e'][] = __('No DB extensions');
|
||||
}
|
||||
$this->dbTypes = $dbTypes;
|
||||
|
||||
|
||||
$this->a = $this->a + $args; //????
|
||||
|
||||
if (empty($args)) {
|
||||
$this->dbhost = 'localhost';
|
||||
$this->dbname = '';
|
||||
$this->dbuser = '';
|
||||
$this->dbprefix = '';
|
||||
$this->username = '';
|
||||
$this->email = '';
|
||||
$this->title = __('My ForkBB Forum');
|
||||
$this->descr = __('Description');
|
||||
$this->baseurl = $this->c->BASE_URL;
|
||||
} else {
|
||||
$this->dbhost = $args['dbhost'];
|
||||
$this->dbname = $args['dbname'];
|
||||
$this->dbuser = $args['dbuser'];
|
||||
$this->dbprefix = $args['dbprefix'];
|
||||
$this->username = $args['username'];
|
||||
$this->email = $args['email'];
|
||||
$this->title = $args['title'];
|
||||
$this->descr = $args['descr'];
|
||||
$this->baseurl = $args['baseurl'];
|
||||
}
|
||||
|
||||
$this->data = $args + [
|
||||
'rev' => $this->c->FORK_REVISION,
|
||||
'formAction' => $this->c->Router->link('Install'),
|
||||
'installLangs' => $installLangs,
|
||||
'installLang' => $installLang,
|
||||
'dbTypes' => $dbTypes,
|
||||
'dbhost' => 'localhost',
|
||||
'dbname' => '',
|
||||
'dbuser' => '',
|
||||
'dbprefix' => '',
|
||||
'username' => '',
|
||||
'email' => '',
|
||||
'title' => __('My ForkBB Forum'),
|
||||
'descr' => __('Description'),
|
||||
'baseurl' => $this->c->BASE_URL,
|
||||
'defaultLangs' => $defaultLangs,
|
||||
'defaultStyles' => $defaultStyles,
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Начальная стадия установки
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function installPost()
|
||||
|
@ -214,7 +218,7 @@ class Install extends Page
|
|||
'rtrim_url' => [$this, 'vRtrimURL']
|
||||
])->setRules([
|
||||
'installlang' => 'string:trim',
|
||||
'dbtype' => ['required|string:trim|in:' . implode(',', array_keys($this->getDBTypes())), __('Database type')],
|
||||
'dbtype' => ['required|string:trim|in:' . implode(',', array_keys($this->DBTypes())), __('Database type')],
|
||||
'dbhost' => ['required|string:trim|check_host', __('Database server hostname')],
|
||||
'dbname' => ['required|string:trim', __('Database name')],
|
||||
'dbuser' => ['string:trim', __('Database username')],
|
||||
|
@ -235,50 +239,53 @@ class Install extends Page
|
|||
if ($v->validation($_POST)) {
|
||||
return $this->installEnd($v);
|
||||
} else {
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
return $this->install($v->getData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка base URL
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $url
|
||||
* @param int $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vRtrimURL(Validator $v, $url, $type)
|
||||
public function vRtrimURL(Validator $v, $url)
|
||||
{
|
||||
return [rtrim($url, '/'), $type, false];
|
||||
return [rtrim($url, '/'), true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка префикса
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $prefix
|
||||
* @param int $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vCheckPrefix(Validator $v, $prefix, $type)
|
||||
public function vCheckPrefix(Validator $v, $prefix)
|
||||
{
|
||||
$error = false;
|
||||
$error = true;
|
||||
if (strlen($prefix) == 0) {
|
||||
} elseif (! preg_match('%^[a-z][a-z\d_]*$%i', $prefix)) {
|
||||
$error = __('Table prefix error', $prefix);
|
||||
} elseif ($v->dbtype == 'sqlite' && strtolower($prefix) == 'sqlite_') {
|
||||
$error = __('Prefix reserved');
|
||||
}
|
||||
return [$prefix, $type, $error];
|
||||
return [$prefix, $error];
|
||||
}
|
||||
|
||||
/**
|
||||
* Полная проверка подключения к БД
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $dbhost
|
||||
* @param int $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vCheckHost(Validator $v, $dbhost, $type)
|
||||
public function vCheckHost(Validator $v, $dbhost)
|
||||
{
|
||||
$this->c->DB_USERNAME = $v->dbuser;
|
||||
$this->c->DB_PASSWORD = $v->dbpass;
|
||||
|
@ -287,7 +294,7 @@ class Install extends Page
|
|||
$dbname = $v->dbname;
|
||||
// есть ошибки, ни чего не проверяем
|
||||
if (! empty($v->getErrors())) {
|
||||
return [$dbhost, $type, false];
|
||||
return [$dbhost, true];
|
||||
}
|
||||
// настройки подключения БД
|
||||
$DBEngine = 'MyISAM';
|
||||
|
@ -314,13 +321,13 @@ class Install extends Page
|
|||
try {
|
||||
$stat = $this->c->DB->statistics();
|
||||
} catch (PDOException $e) {
|
||||
return [$dbhost, $type, $e->getMessage()];
|
||||
return [$dbhost, $e->getMessage()];
|
||||
}
|
||||
// проверка наличия таблицы пользователей в БД
|
||||
try {
|
||||
$stmt = $this->c->DB->query('SELECT 1 FROM ::users WHERE id=1 LIMIT 1');
|
||||
if (! empty($stmt->fetch())) {
|
||||
return [$dbhost, $type, __('Existing table error', $v->dbprefix, $v->dbname)];
|
||||
return [$dbhost, __('Existing table error', $v->dbprefix, $v->dbname)];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// все отлично, таблица пользователей не найдена
|
||||
|
@ -329,12 +336,14 @@ class Install extends Page
|
|||
if (isset($stat['character_set_database']) && $stat['character_set_database'] == 'utf8') {
|
||||
$this->c->DB_DSN = str_replace('charset=utf8mb4', 'charset=utf8', $this->c->DB_DSN);
|
||||
}
|
||||
return [$dbhost, $type, false];
|
||||
return [$dbhost, true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Завершение установки форума
|
||||
*
|
||||
* @param Validator $v
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
protected function installEnd(Validator $v)
|
||||
|
@ -1002,7 +1011,7 @@ class Install extends Page
|
|||
throw new RuntimeException('No access to main.dist.php.');
|
||||
}
|
||||
|
||||
$repl = [
|
||||
$repl = [ //????
|
||||
'_BASE_URL_' => $v->baseurl,
|
||||
'_DB_DSN_' => $this->c->DB_DSN,
|
||||
'_DB_USERNAME_' => $this->c->DB_USERNAME,
|
||||
|
@ -1016,7 +1025,7 @@ class Install extends Page
|
|||
}
|
||||
$result = file_put_contents($this->c->DIR_CONFIG . '/main.php', $config);
|
||||
if (false === $result) {
|
||||
throw new RuntimeException('No write to main.php.');
|
||||
throw new RuntimeException('No write to main.php');
|
||||
}
|
||||
|
||||
return $this->c->Redirect->toIndex();
|
||||
|
|
|
@ -3,65 +3,34 @@
|
|||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Maintenance extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'maintenance';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = null;
|
||||
|
||||
/**
|
||||
* HTTP статус ответа для данной страницы
|
||||
* @var int
|
||||
*/
|
||||
protected $httpStatus = 503;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
$container->Lang->load('common', $this->config['o_default_lang']);
|
||||
$container->Lang->load('common', $container->config->o_default_lang);
|
||||
|
||||
parent::__construct($container);
|
||||
|
||||
$this->httpStatus = 503;
|
||||
$this->nameTpl = 'maintenance';
|
||||
# $this->onlinePos = null; //????
|
||||
# $this->robots = 'noindex';
|
||||
$this->titles = __('Maintenance');
|
||||
# $this->fNavigation = null; //????
|
||||
$this->maintenanceMessage = $this->c->config->o_maintenance_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг готовности данных
|
||||
* @return bool
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function isReady()
|
||||
public function prepare()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$this->titles[] = __('Maintenance');
|
||||
return [
|
||||
'maintenanceMessage' => $this->config['o_maintenance_message'],
|
||||
'pageTitle' => $this->pageTitle(),
|
||||
'pageHeaders' => $this->pageHeaders(),
|
||||
'fTitle' => $this->config['o_board_title'],
|
||||
'fDescription' => $this->config['o_board_desc'],
|
||||
'fNavigation' => null,
|
||||
'fIndex' => $this->index,
|
||||
'fAnnounce' => null,
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
'fIswev' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,19 +8,22 @@ trait OnlineTrait
|
|||
* Получение информации об онлайн посетителях
|
||||
* @return null|array
|
||||
*/
|
||||
protected function getUsersOnlineInfo()
|
||||
protected function usersOnlineInfo()
|
||||
{
|
||||
if ($this->config['o_users_online'] == '1') {
|
||||
if ($this->c->config->o_users_online == '1') {
|
||||
// данные онлайн посетителей
|
||||
$this->c->Online->calc($this);
|
||||
$users = $this->c->Online->users; //????
|
||||
$guests = $this->c->Online->guests;
|
||||
$bots = $this->c->Online->bots;
|
||||
|
||||
$list = [];
|
||||
$data = [
|
||||
'max' => $this->number($this->config['st_max_users']),
|
||||
'max_time' => $this->time($this->config['st_max_users_time']),
|
||||
'max' => $this->number($this->c->config->st_max_users),
|
||||
'max_time' => $this->time($this->c->config->st_max_users_time),
|
||||
];
|
||||
|
||||
// данные онлайн посетителей
|
||||
list($users, $guests, $bots) = $this->c->Online->handle($this);
|
||||
$list = [];
|
||||
|
||||
if ($this->c->user->gViewUsers == '1') {
|
||||
if ($this->c->user->g_view_users == '1') {
|
||||
foreach ($users as $id => $cur) {
|
||||
$list[] = [
|
||||
$this->c->Router->link('User', [
|
||||
|
|
68
app/Models/Pages/Post.php
Normal file
68
app/Models/Pages/Post.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
class Post extends Page
|
||||
{
|
||||
use UsersTrait;
|
||||
use OnlineTrait;
|
||||
use CrumbTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'post';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'post';
|
||||
|
||||
/**
|
||||
* Данные по текущей теме
|
||||
* @var array
|
||||
*/
|
||||
protected $topic;
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function newTopic(array $args)
|
||||
{
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
// раздел отсутствует в доступных
|
||||
if (empty($fDesc[$args['id']])) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$parent = isset($fDesc[$args['id']][0]) ? $fDesc[$args['id']][0] : 0;
|
||||
$perm = $fTree[$parent][$args['id']];
|
||||
|
||||
// раздел является ссылкой
|
||||
if (null !== $perm['redirect_url']) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$vars = [':fid' => $args['id']];
|
||||
$sql = 'SELECT f.* FROM ::forums AS f WHERE f.id=?i:fid';
|
||||
|
||||
$forum = $this->c->DB->query($sql, $vars)->fetch();
|
||||
$user = $this->c->user;
|
||||
|
||||
$moders = empty($forum['moderators']) ? [] : array_flip(unserialize($forum['moderators']));
|
||||
|
||||
if (! $user->isAdmin
|
||||
&& (! $user->isAdmMod || ! isset($moders[$user->id]))
|
||||
&& (null === $perm['post_topics'] && $user->g_post_topics == '0' || $perm['post_topics'] == '0')
|
||||
) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -2,57 +2,29 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Redirect extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = null;
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = null;
|
||||
|
||||
/**
|
||||
* Адрес перехода
|
||||
* @var string
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots = 'noindex';
|
||||
|
||||
/**
|
||||
* Возвращает флаг готовности данных
|
||||
* @return bool
|
||||
*/
|
||||
public function isReady()
|
||||
{
|
||||
return ! empty($this->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Перенаправление на главную страницу форума
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function toIndex()
|
||||
{
|
||||
return $this->setPage('Index')->setMessage(__('Redirecting to index'));
|
||||
return $this->page('Index')->message(__('Redirecting to index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Задает адрес перехода
|
||||
*
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function setPage($marker, array $args = [])
|
||||
public function page($marker, array $args = [])
|
||||
{
|
||||
$this->link = $this->c->Router->link($marker, $args);
|
||||
return $this;
|
||||
|
@ -60,10 +32,12 @@ class Redirect extends Page
|
|||
|
||||
/**
|
||||
* Задает ссылку для перехода
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function setUrl($url)
|
||||
public function url($url)
|
||||
{
|
||||
$this->link = $url;
|
||||
return $this;
|
||||
|
@ -71,47 +45,47 @@ class Redirect extends Page
|
|||
|
||||
/**
|
||||
* Задает сообщение
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function setMessage($message)
|
||||
public function message($message)
|
||||
{
|
||||
// переадресация без вывода сообщения
|
||||
if ($this->config['o_redirect_delay'] == '0') {
|
||||
if ($this->c->config->o_redirect_delay == '0') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->nameTpl = 'layouts/redirect';
|
||||
$this->titles[] = __('Redirecting');
|
||||
$this->data = [
|
||||
'message' => $message,
|
||||
'timeout' => (int) $this->config['o_redirect_delay'], //???? перенести в заголовки?
|
||||
];
|
||||
$this->titles = __('Redirecting');
|
||||
$this->robots = 'noindex';
|
||||
$this->message = $message;
|
||||
$this->timeout = (int) $this->c->config->o_redirect_delay; //???? перенести в заголовки?
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает HTTP заголовки страницы
|
||||
* $this->httpHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function httpHeaders()
|
||||
protected function getHttpHeaders()
|
||||
{
|
||||
// переадресация без вывода сообщения
|
||||
if (empty($this->data)) {
|
||||
if (null === $this->nameTpl) {
|
||||
$this->httpHeaders = [
|
||||
'Location: ' . $this->link, //????
|
||||
];
|
||||
}
|
||||
return parent::httpHeaders();
|
||||
return parent::getHttpHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для шаблона
|
||||
* @return array
|
||||
* Подготовка страницы к отображению
|
||||
*/
|
||||
public function getData()
|
||||
public function prepare()
|
||||
{
|
||||
$this->data['link'] = $this->link;
|
||||
return parent::getData();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,37 +4,15 @@ namespace ForkBB\Models\Pages;
|
|||
|
||||
use ForkBB\Core\Validator;
|
||||
use ForkBB\Core\Exceptions\MailException;
|
||||
use ForkBB\Models\Page;
|
||||
use ForkBB\Models\User;
|
||||
|
||||
class Register extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'register';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'register';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации
|
||||
* @var string
|
||||
*/
|
||||
protected $index = 'register';
|
||||
|
||||
/**
|
||||
* Переменная для meta name="robots"
|
||||
* @var string
|
||||
*/
|
||||
protected $robots = 'noindex';
|
||||
|
||||
/**
|
||||
* Обработчик регистрации
|
||||
* @retrun Page
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function reg()
|
||||
{
|
||||
|
@ -62,40 +40,47 @@ class Register extends Page
|
|||
return $this->regEnd($v);
|
||||
}
|
||||
|
||||
$this->iswev = $v->getErrors();
|
||||
$this->fIswev = $v->getErrors();
|
||||
|
||||
// нет согласия с правилами
|
||||
if (isset($this->iswev['cancel'])) {
|
||||
return $this->c->Redirect->setPage('Index')->setMessage(__('Reg cancel redirect'));
|
||||
if (isset($this->fIswev['cancel'])) {
|
||||
return $this->c->Redirect->page('Index')->message(__('Reg cancel redirect'));
|
||||
}
|
||||
|
||||
$this->titles[] = __('Register');
|
||||
$this->data = [
|
||||
'formAction' => $this->c->Router->link('RegisterForm'),
|
||||
'formToken' => $this->c->Csrf->create('RegisterForm'),
|
||||
'agree' => $v->agree,
|
||||
'on' => '1',
|
||||
'email' => $v->email,
|
||||
'username' => $v->username,
|
||||
];
|
||||
$this->fIndex = 'register';
|
||||
$this->nameTpl = 'register';
|
||||
$this->onlinePos = 'register';
|
||||
$this->titles = __('Register');
|
||||
$this->robots = 'noindex';
|
||||
$this->formAction = $this->c->Router->link('RegisterForm');
|
||||
$this->formToken = $this->c->Csrf->create('RegisterForm');
|
||||
$this->agree = $v->agree;
|
||||
$this->on = '1';
|
||||
$this->email = $v->email;
|
||||
$this->username = $v->username;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка email
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $username
|
||||
* @param string $email
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vCheckEmail(Validator $v, $email)
|
||||
{
|
||||
$error = false;
|
||||
$user = $this->c->ModelUser;
|
||||
$user->__email = $email;
|
||||
|
||||
// email забанен
|
||||
if ($this->c->CheckBans->isBanned(null, $email) > 0) {
|
||||
if ($this->c->bans->isBanned($user) > 0) {
|
||||
$error = __('Banned email');
|
||||
// найден хотя бы 1 юзер с таким же email
|
||||
} elseif (empty($v->getErrors()) && $this->c->UserMapper->getUser($email, 'email') !== 0) {
|
||||
} elseif (empty($v->getErrors()) && $user->load($email, 'email') !== 0) {
|
||||
$error = __('Dupe email');
|
||||
}
|
||||
return [$email, $error];
|
||||
|
@ -103,25 +88,30 @@ class Register extends Page
|
|||
|
||||
/**
|
||||
* Дополнительная проверка username
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $username
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vCheckUsername(Validator $v, $username)
|
||||
{
|
||||
$username = preg_replace('%\s+%su', ' ', $username);
|
||||
$error = false;
|
||||
$user = $this->c->ModelUser;
|
||||
$user->__username = $username;
|
||||
|
||||
// username = Гость
|
||||
if (preg_match('%^(guest|' . preg_quote(__('Guest'), '%') . ')$%iu', $username)) {
|
||||
$error = __('Username guest');
|
||||
// цензура
|
||||
} elseif ($this->censor($username) !== $username) {
|
||||
} elseif ($this->c->censorship->censor($username) !== $username) {
|
||||
$error = __('Username censor');
|
||||
// username забанен
|
||||
} elseif ($this->c->CheckBans->isBanned($username) > 0) {
|
||||
} elseif ($this->c->bans->isBanned($user) > 0) {
|
||||
$error = __('Banned username');
|
||||
// есть пользователь с похожим именем
|
||||
} elseif (empty($v->getErrors()) && ! $this->c->UserMapper->isUnique($username)) {
|
||||
} elseif (empty($v->getErrors()) && ! $user->isUnique()) {
|
||||
$error = __('Username not unique');
|
||||
}
|
||||
return [$username, $error];
|
||||
|
@ -129,40 +119,50 @@ class Register extends Page
|
|||
|
||||
/**
|
||||
* Завершение регистрации
|
||||
*
|
||||
* @param array @data
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
protected function regEnd(Validator $v)
|
||||
{
|
||||
if ($this->config['o_regs_verify'] == '1') {
|
||||
if ($this->c->config->o_regs_verify == '1') {
|
||||
$groupId = $this->c->GROUP_UNVERIFIED;
|
||||
$key = 'w' . $this->c->Secury->randomPass(79);
|
||||
} else {
|
||||
$groupId = $this->config['o_default_user_group'];
|
||||
$groupId = $this->c->config->o_default_user_group;
|
||||
$key = null;
|
||||
}
|
||||
|
||||
$newUserId = $this->c->UserMapper->newUser(new User([
|
||||
'group_id' => $groupId,
|
||||
'username' => $v->username,
|
||||
'password' => password_hash($v->password, PASSWORD_DEFAULT),
|
||||
'email' => $v->email,
|
||||
'email_confirmed' => 0,
|
||||
'activate_string' => $key,
|
||||
'u_mark_all_read' => time(),
|
||||
], $this->c));
|
||||
$user = $this->c->ModelUser;
|
||||
$user->username = $v->username;
|
||||
$user->password = password_hash($v->password, PASSWORD_DEFAULT);
|
||||
$user->group_id = $groupId;
|
||||
$user->email = $v->email;
|
||||
$user->email_confirmed = 0;
|
||||
$user->activate_string = $key;
|
||||
$user->u_mark_all_read = time();
|
||||
$user->email_setting = $this->c->config->o_default_email_setting;
|
||||
$user->timezone = $this->c->config->o_default_timezone;
|
||||
$user->dst = $this->c->config->o_default_dst;
|
||||
$user->language = $user->language;
|
||||
$user->style = $user->style;
|
||||
$user->registered = time();
|
||||
$user->registration_ip = $this->c->user->ip;
|
||||
|
||||
$newUserId = $user->insert();
|
||||
|
||||
// обновление статистики по пользователям
|
||||
if ($this->config['o_regs_verify'] != '1') {
|
||||
if ($this->c->config->o_regs_verify != '1') {
|
||||
$this->c->{'users_info update'};
|
||||
}
|
||||
|
||||
// уведомление о регистрации
|
||||
if ($this->config['o_regs_report'] == '1' && $this->config['o_mailing_list'] != '') {
|
||||
if ($this->c->config->o_regs_report == '1' && $this->c->config->o_mailing_list != '') {
|
||||
$tplData = [
|
||||
'fTitle' => $this->config['o_board_title'],
|
||||
'fTitle' => $this->c->config->o_board_title,
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
'fMailer' => __('Mailer', $this->config['o_board_title']),
|
||||
'fMailer' => __('Mailer', $this->c->config->o_board_title),
|
||||
'username' => $v->username,
|
||||
'userLink' => $this->c->Router->link('User', ['id' => $newUserId, 'name' => $v->username]),
|
||||
];
|
||||
|
@ -171,9 +171,9 @@ class Register extends Page
|
|||
$this->c->Mail
|
||||
->reset()
|
||||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->config['o_default_lang'])
|
||||
->setTo($this->config['o_mailing_list'])
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setLanguage($this->c->config->o_default_lang)
|
||||
->setTo($this->c->config->o_mailing_list)
|
||||
->setFrom($this->c->config->o_webmaster_email, __('Mailer', $this->c->config->o_board_title))
|
||||
->setTpl('new_user.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
|
@ -184,13 +184,13 @@ class Register extends Page
|
|||
$this->c->Lang->load('register');
|
||||
|
||||
// отправка письма активации аккаунта
|
||||
if ($this->config['o_regs_verify'] == '1') {
|
||||
if ($this->c->config->o_regs_verify == '1') {
|
||||
$hash = $this->c->Secury->hash($newUserId . $key);
|
||||
$link = $this->c->Router->link('RegActivate', ['id' => $newUserId, 'key' => $key, 'hash' => $hash]);
|
||||
$tplData = [
|
||||
'fTitle' => $this->config['o_board_title'],
|
||||
'fTitle' => $this->c->config->o_board_title,
|
||||
'fRootLink' => $this->c->Router->link('Index'),
|
||||
'fMailer' => __('Mailer', $this->config['o_board_title']),
|
||||
'fMailer' => __('Mailer', $this->c->config->o_board_title),
|
||||
'username' => $v->username,
|
||||
'link' => $link,
|
||||
];
|
||||
|
@ -201,7 +201,7 @@ class Register extends Page
|
|||
->setFolder($this->c->DIR_LANG)
|
||||
->setLanguage($this->c->user->language)
|
||||
->setTo($v->email)
|
||||
->setFrom($this->config['o_webmaster_email'], __('Mailer', $this->config['o_board_title']))
|
||||
->setFrom($this->c->config->o_webmaster_email, __('Mailer', $this->c->config->o_board_title))
|
||||
->setTpl('welcome.tpl', $tplData)
|
||||
->send();
|
||||
} catch (MailException $e) {
|
||||
|
@ -210,56 +210,49 @@ class Register extends Page
|
|||
|
||||
// письмо активации аккаунта отправлено
|
||||
if ($isSent) {
|
||||
return $this->c->Message->message(__('Reg email', $this->config['o_admin_email']), false, 200);
|
||||
return $this->c->Message->message(__('Reg email', $this->c->config->o_admin_email), false, 200);
|
||||
// форма сброса пароля
|
||||
} else {
|
||||
return $this->c->Auth->setIswev([
|
||||
'w' => [
|
||||
__('Error welcom mail', $this->config['o_admin_email']),
|
||||
],
|
||||
])->forget([
|
||||
'_email' => $v->email,
|
||||
]);
|
||||
$auth = $this->c->Auth;
|
||||
$auth->fIswev = ['w' => [__('Error welcom mail', $this->c->config->o_admin_email)]];
|
||||
return $auth->forget(['_email' => $v->email]);
|
||||
}
|
||||
// форма логина
|
||||
} else {
|
||||
return $this->c->Auth->setIswev([
|
||||
's' => [
|
||||
__('Reg complete'),
|
||||
],
|
||||
])->login([
|
||||
'_username' => $v->username,
|
||||
]);
|
||||
$auth = $this->c->Auth;
|
||||
$auth->fIswev = ['s' => [__('Reg complete')]];
|
||||
return $auth->login(['_username' => $v->username]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация аккаунта
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function activate(array $args)
|
||||
{
|
||||
if (! hash_equals($args['hash'], $this->c->Secury->hash($args['id'] . $args['key']))
|
||||
|| ! ($user = $this->c->UserMapper->getUser($args['id'])) instanceof User
|
||||
|| empty($user->activateString)
|
||||
|| $user->activateString{0} !== 'w'
|
||||
|| ! hash_equals($user->activateString, $args['key'])
|
||||
|| ! ($user = $this->c->ModelUser->load($args['id'])) instanceof User
|
||||
|| empty($user->activate_string)
|
||||
|| $user->activate_string{0} !== 'w'
|
||||
|| ! hash_equals($user->activate_string, $args['key'])
|
||||
) {
|
||||
return $this->c->Message->message(__('Bad request'), false);
|
||||
}
|
||||
|
||||
$this->c->UserMapper->updateUser($user->id, ['group_id' => $this->config['o_default_user_group'], 'email_confirmed' => 1, 'activate_string' => null]);
|
||||
$user->group_id = $this->c->config->o_default_user_group;
|
||||
$user->email_confirmed = 1;
|
||||
$user->activate_string = null;
|
||||
$user->update();
|
||||
$this->c->{'users_info update'};
|
||||
|
||||
$this->c->Lang->load('register');
|
||||
|
||||
return $this->c->Auth->setIswev([
|
||||
's' => [
|
||||
__('Reg complete'),
|
||||
],
|
||||
])->login([
|
||||
'_username' => $user->username,
|
||||
]);
|
||||
$auth = $this->c->Auth;
|
||||
$auth->fIswev = ['s' => [__('Reg complete')]];
|
||||
return $auth->login(['_username' => $v->username]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,64 +2,49 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Rules extends Page
|
||||
{
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
*/
|
||||
protected $nameTpl = 'rules';
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'rules';
|
||||
|
||||
/**
|
||||
* Указатель на активный пункт навигации
|
||||
* @var string
|
||||
*/
|
||||
protected $index = 'rules';
|
||||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function view()
|
||||
{
|
||||
$this->titles[] = __('Forum rules');
|
||||
$this->data = [
|
||||
'title' => __('Forum rules'),
|
||||
'rules' => $this->config['o_rules_message'],
|
||||
'formAction' => null,
|
||||
];
|
||||
|
||||
$this->canonical = $this->c->Router->link('Rules');
|
||||
$this->fIndex = 'rules';
|
||||
$this->nameTpl = 'rules';
|
||||
$this->onlinePos = 'rules';
|
||||
$this->canonical = $this->c->Router->link('Rules');
|
||||
$this->titles = __('Forum rules');
|
||||
$this->title = __('Forum rules');
|
||||
$this->rules = $this->c->config->o_rules_message;
|
||||
$this->formAction = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает данные для шаблона
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function confirmation()
|
||||
{
|
||||
$this->index = 'register';
|
||||
$this->robots = 'noindex';
|
||||
$this->c->Lang->load('register');
|
||||
|
||||
$this->titles[] = __('Forum rules');
|
||||
$this->data = [
|
||||
'title' => __('Forum rules'),
|
||||
'rules' => $this->config['o_rules'] == '1' ?
|
||||
$this->config['o_rules_message']
|
||||
: __('If no rules'),
|
||||
'formAction' => $this->c->Router->link('RegisterForm'),
|
||||
'formToken' => $this->c->Csrf->create('RegisterForm'),
|
||||
'formHash' => $this->c->Csrf->create('Register'),
|
||||
];
|
||||
$this->fIndex = 'register';
|
||||
$this->nameTpl = 'rules';
|
||||
$this->onlinePos = 'rules';
|
||||
$this->robots = 'noindex';
|
||||
$this->titles = __('Forum rules');
|
||||
$this->title = __('Forum rules');
|
||||
$this->rules = $this->c->config->o_rules == '1' ? $this->c->config->o_rules_message : __('If no rules');
|
||||
$this->formAction = $this->c->Router->link('RegisterForm');
|
||||
$this->formToken = $this->c->Csrf->create('RegisterForm');
|
||||
$this->formHash = $this->c->Csrf->create('Register');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
|
||||
class Topic extends Page
|
||||
{
|
||||
use UsersTrait;
|
||||
|
@ -9,60 +11,104 @@ class Topic extends Page
|
|||
use CrumbTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
* Данные по текущей теме
|
||||
* @var array
|
||||
*/
|
||||
protected $nameTpl = 'topic';
|
||||
protected $curTopic;
|
||||
|
||||
/**
|
||||
* Позиция для таблицы онлайн текущего пользователя
|
||||
* @var null|string
|
||||
*/
|
||||
protected $onlinePos = 'topic';
|
||||
|
||||
/**
|
||||
* Тип обработки пользователей онлайн
|
||||
* Если false, то идет обновление данных
|
||||
* Если true, то идет возврат данных (смотрите $onlineFilter)
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineType = true;
|
||||
|
||||
/**
|
||||
* Тип возврата данных при onlineType === true
|
||||
* Если true, то из online должны вернутся только пользователи находящиеся на этой же странице
|
||||
* Если false, то все пользователи online
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineFilter = true;
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* Переход к первому новому сообщению темы (или в конец)
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function viewNew(array $args)
|
||||
{
|
||||
public function viewNew(array $args)
|
||||
{
|
||||
$topic = $this->curTopic($args['id']);
|
||||
if (false === $topic) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
}
|
||||
if (! $this->c->user->isGuest) {
|
||||
$upper = max(
|
||||
(int) $this->c->user->last_visit,
|
||||
(int) $this->c->user->u_mark_all_read,
|
||||
(int) $topic['mf_mark_all_read'],
|
||||
(int) $topic['mt_last_visit']
|
||||
);
|
||||
|
||||
if ($upper < $topic['last_post']) {
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':visit' => $upper,
|
||||
];
|
||||
$sql = 'SELECT MIN(id) FROM ::posts WHERE topic_id=?i:tid AND posted>?i:visit';
|
||||
|
||||
$pid = $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
if (! empty($pid)) {
|
||||
return $this->c->Redirect->page('ViewPost', ['id' => $pid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->viewLast(['id' => $topic['id']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* Переход к первому непрочитанному сообщению (или в конец)
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function viewUnread(array $args)
|
||||
{
|
||||
public function viewUnread(array $args)
|
||||
{
|
||||
$topic = $this->curTopic($args['id']);
|
||||
if (false === $topic) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
}
|
||||
if (! $this->c->user->isGuest) {
|
||||
$lower = max(
|
||||
(int) $this->c->user->u_mark_all_read,
|
||||
(int) $topic['mf_mark_all_read'],
|
||||
(int) $topic['mt_last_read']
|
||||
);
|
||||
|
||||
if ($lower < $topic['last_post']) {
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':visit' => $lower,
|
||||
];
|
||||
$sql = 'SELECT MIN(id) FROM ::posts WHERE topic_id=?i:tid AND posted>?i:visit';
|
||||
|
||||
$pid = $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
if (! empty($pid)) {
|
||||
return $this->c->Redirect->page('ViewPost', ['id' => $pid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->viewLast(['id' => $topic['id']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Переход к последнему сообщению темы
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function viewLast(array $args)
|
||||
{
|
||||
public function viewLast(array $args)
|
||||
{
|
||||
$topic = $this->curTopic($args['id']);
|
||||
if (false === $topic) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
];
|
||||
|
@ -74,122 +120,154 @@ class Topic extends Page
|
|||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
return $this->c->Redirect->setPage('ViewPost', ['id' => $pid]);
|
||||
return $this->c->Redirect->page('ViewPost', ['id' => $pid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр темы по номеру сообщения
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function viewPost(array $args)
|
||||
{
|
||||
$vars = [
|
||||
':pid' => $args['id'],
|
||||
':uid' => $this->c->user->id,
|
||||
];
|
||||
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed, 0 AS mf_mark_all_read, 0 AS mt_last_visit, 0 AS mt_last_read
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
} else {
|
||||
$sql = 'SELECT t.*, f.moderators, s.user_id AS is_subscribed, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND f.id=mof.fid)
|
||||
LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
}
|
||||
|
||||
return $this->view($sql, $vars, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр темы по ее номеру
|
||||
* @param array $args
|
||||
* @return Page
|
||||
* Получение данных по текущей теме
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param mixed $pid
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function viewTopic(array $args)
|
||||
protected function curTopic($id, $pid = null)
|
||||
{
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':uid' => $this->c->user->id,
|
||||
];
|
||||
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed, 0 AS mf_mark_all_read, 0 AS mt_last_visit, 0 AS mt_last_read
|
||||
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, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
|
||||
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)
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND f.id=mof.fid)
|
||||
LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
|
||||
WHERE t.id=?i:tid AND t.moved_to IS NULL';
|
||||
if ($this->curTopic) {
|
||||
return $this->curTopic;
|
||||
}
|
||||
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
if (isset($pid)) {
|
||||
$vars = [
|
||||
':pid' => $pid,
|
||||
':uid' => $this->c->user->id,
|
||||
];
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed, 0 AS mf_mark_all_read, 0 AS mt_last_visit, 0 AS mt_last_read
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
|
||||
return $this->view($sql, $vars, $page);
|
||||
}
|
||||
} else {
|
||||
$sql = 'SELECT t.*, f.moderators, s.user_id AS is_subscribed, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND f.id=mof.fid)
|
||||
LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
}
|
||||
} else {
|
||||
$vars = [
|
||||
':tid' => $id,
|
||||
':uid' => $this->c->user->id,
|
||||
];
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed, 0 AS mf_mark_all_read, 0 AS mt_last_visit, 0 AS mt_last_read
|
||||
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';
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param string $sql
|
||||
* @param array $vars
|
||||
* @param int|null $page
|
||||
* @return Page
|
||||
*/
|
||||
protected function view($sql, array $vars, $page)
|
||||
{
|
||||
$user = $this->c->user;
|
||||
|
||||
$vars[':uid'] = $user->id;
|
||||
} else {
|
||||
$sql = 'SELECT t.*, f.moderators, s.user_id AS is_subscribed, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
|
||||
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)
|
||||
LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND f.id=mof.fid)
|
||||
LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
|
||||
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');
|
||||
return false;
|
||||
}
|
||||
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
// раздел отсутствует в доступных
|
||||
if (empty($fDesc[$topic['forum_id']])) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->curTopic = $topic;
|
||||
return $topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр темы по номеру сообщения
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function viewPost(array $args)
|
||||
{
|
||||
$topic = $this->curTopic(null, $args['id']);
|
||||
if (false === $topic) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
return $this->view($topic, $args['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр темы по ее номеру
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function viewTopic(array $args)
|
||||
{
|
||||
$topic = $this->curTopic($args['id']);
|
||||
if (false === $topic) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
return $this->view($topic, null, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
*
|
||||
* @param array $topic
|
||||
* @param int|null $pid
|
||||
* @param int|null $page
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
protected function view(array $topic, $pid, $page = null)
|
||||
{
|
||||
$user = $this->c->user;
|
||||
|
||||
if (null === $page) {
|
||||
$vars[':tid'] = $topic['id'];
|
||||
$vars = [
|
||||
':tid' => $topic['id'],
|
||||
':pid' => $pid,
|
||||
];
|
||||
$sql = 'SELECT COUNT(id) FROM ::posts WHERE topic_id=?i:tid AND id<?i:pid';
|
||||
|
||||
$num = 1 + $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
$page = ceil($num / $user->dispPosts);
|
||||
$page = ceil($num / $user->disp_posts);
|
||||
}
|
||||
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
$pages = ceil(($topic['num_replies'] + 1) / $user->dispPosts);
|
||||
$pages = ceil(($topic['num_replies'] + 1) / $user->disp_posts);
|
||||
// попытка открыть страницу которой нет
|
||||
if ($page < 1 || $page > $pages) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $user->dispPosts;
|
||||
$offset = ($page - 1) * $user->disp_posts;
|
||||
$vars = [
|
||||
':tid' => $topic['id'],
|
||||
':offset' => $offset,
|
||||
':rows' => $user->dispPosts,
|
||||
':rows' => $user->disp_posts,
|
||||
];
|
||||
$sql = 'SELECT id
|
||||
FROM ::posts
|
||||
|
@ -200,9 +278,13 @@ class Topic extends Page
|
|||
|
||||
// нарушена синхронизация количества сообщений в темах
|
||||
if (empty($ids)) {
|
||||
return $this->viewLast($topic['id']);
|
||||
return $this->viewLast(['id' => $topic['id']]);
|
||||
}
|
||||
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
$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']];
|
||||
|
@ -217,7 +299,7 @@ class Topic extends Page
|
|||
} elseif ($topic['closed'] == '1') {
|
||||
$newOn = false;
|
||||
} elseif ($perm['post_replies'] === 1
|
||||
|| (null === $perm['post_replies'] && $user->gPostReplies == '1')
|
||||
|| (null === $perm['post_replies'] && $user->g_post_replies == '1')
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]))
|
||||
) {
|
||||
$newOn = true;
|
||||
|
@ -255,20 +337,20 @@ class Topic extends Page
|
|||
|
||||
// парсер и его настройка для сообщений
|
||||
$bbcodes = include $this->c->DIR_CONFIG . '/defaultBBCode.php';
|
||||
$smilies = $this->c->smilies;
|
||||
$smilies = $this->c->smilies->list; //????
|
||||
foreach ($smilies as &$cur) {
|
||||
$cur = $this->c->PUBLIC_URL . '/img/sm/' . $cur;
|
||||
}
|
||||
unset($cur);
|
||||
$bbInfo = $this->c->BBCODE_INFO;
|
||||
$bbWList = $this->config['p_message_bbcode'] == '1' ? null : [];
|
||||
$bbBList = $this->config['p_message_img_tag'] == '1' ? [] : ['img'];
|
||||
$bbWList = $this->c->config->p_message_bbcode == '1' ? null : [];
|
||||
$bbBList = $this->c->config->p_message_img_tag == '1' ? [] : ['img'];
|
||||
$parser = $this->c->Parser;
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr('isSign', false)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList);
|
||||
if ($user->showSmilies == '1') {
|
||||
if ($user->show_smilies == '1') {
|
||||
$parser->setSmilies($smilies)
|
||||
->setSmTpl($bbInfo['smTpl'], $bbInfo['smTplTag'], $bbInfo['smTplBl']);
|
||||
}
|
||||
|
@ -287,7 +369,7 @@ class Topic extends Page
|
|||
$post = [
|
||||
'poster' => $cur['username'],
|
||||
'poster_id' => $cur['poster_id'],
|
||||
'poster_title' => $this->censor($this->userGetTitle($cur)),
|
||||
'poster_title' => $this->c->censorship->censor($this->userGetTitle($cur)),
|
||||
'poster_avatar' => null,
|
||||
'poster_registered' => null,
|
||||
'poster_location' => null,
|
||||
|
@ -299,13 +381,13 @@ class Topic extends Page
|
|||
|
||||
];
|
||||
if ($cur['poster_id'] > 1) {
|
||||
if ($user->gViewUsers == '1') {
|
||||
if ($user->g_view_users == '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') {
|
||||
if ($this->c->config->o_avatars == '1' && $user->show_avatars == '1') {
|
||||
$post['poster_avatar'] = $this->userGetAvatarLink($cur['poster_id']);
|
||||
}
|
||||
if ($this->config['o_show_user_info'] == '1') {
|
||||
if ($this->c->config->o_show_user_info == '1') {
|
||||
$post['poster_info_add'] = true;
|
||||
|
||||
$post['poster_registered'] = $this->time($cur['registered'], true);
|
||||
|
@ -314,7 +396,7 @@ class Topic extends Page
|
|||
$post['poster_num_posts'] = $cur['num_posts'];
|
||||
|
||||
if ($cur['location'] != '') {
|
||||
$post['poster_location'] = $this->censor($cur['location']);
|
||||
$post['poster_location'] = $this->c->censorship->censor($cur['location']);
|
||||
}
|
||||
if (isset($genders[$cur['gender']])) {
|
||||
$post['poster_gender'] = $genders[$cur['gender']];
|
||||
|
@ -324,9 +406,9 @@ class Topic extends Page
|
|||
|
||||
$posters[$cur['poster_id']] = $post;
|
||||
|
||||
if ($this->config['o_signatures'] == '1'
|
||||
if ($this->c->config->o_signatures == '1'
|
||||
&& $cur['signature'] != ''
|
||||
&& $user->showSig == '1'
|
||||
&& $user->show_sig == '1'
|
||||
&& ! isset($signs[$cur['poster_id']])
|
||||
) {
|
||||
$signs[$cur['poster_id']] = $cur['signature'];
|
||||
|
@ -342,8 +424,8 @@ class Topic extends Page
|
|||
|
||||
$timeMax = max($timeMax, $cur['posted']);
|
||||
|
||||
$parser->parse($this->censor($cur['message']));
|
||||
if ($this->config['o_smilies'] == '1' && $user->showSmilies == '1' && $cur['hide_smilies'] == '0') {
|
||||
$parser->parse($this->c->censorship->censor($cur['message']));
|
||||
if ($this->c->config->o_smilies == '1' && $user->show_smilies == '1' && $cur['hide_smilies'] == '0') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
$post['message'] = $parser->getHtml();
|
||||
|
@ -363,18 +445,18 @@ class Topic extends Page
|
|||
$controls['report'] = [$this->c->Router->link('ReportPost', $vars), 'Report'];
|
||||
}
|
||||
if ($user->isAdmin
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]) && ! in_array($cur['poster_id'], $this->c->admins))
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]) && ! in_array($cur['poster_id'], $this->c->admins->list)) //????
|
||||
) {
|
||||
$controls['delete'] = [$this->c->Router->link('DeletePost', $vars), 'Delete'];
|
||||
$controls['edit'] = [$this->c->Router->link('EditPost', $vars), 'Edit'];
|
||||
} elseif ($topic['closed'] != '1'
|
||||
&& $cur['poster_id'] == $user->id
|
||||
&& ($user->gDeleditInterval == '0' || $cur['edit_post'] == '1' || time() - $cur['posted'] < $user->gDeleditInterval)
|
||||
&& ($user->g_deledit_interval == '0' || $cur['edit_post'] == '1' || time() - $cur['posted'] < $user->g_deledit_interval)
|
||||
) {
|
||||
if (($cur['id'] == $topic['first_post_id'] && $user->gDeleteTopics == '1') || ($cur['id'] != $topic['first_post_id'] && $user->gDeletePosts == '1')) {
|
||||
if (($cur['id'] == $topic['first_post_id'] && $user->g_delete_topics == '1') || ($cur['id'] != $topic['first_post_id'] && $user->g_delete_posts == '1')) {
|
||||
$controls['delete'] = [$this->c->Router->link('DeletePost', $vars), 'Delete'];
|
||||
}
|
||||
if ($user->gEditPosts == '1') {
|
||||
if ($user->g_edit_posts == '1') {
|
||||
$controls['edit'] = [$this->c->Router->link('EditPost', $vars), 'Edit'];
|
||||
}
|
||||
}
|
||||
|
@ -389,15 +471,15 @@ class Topic extends Page
|
|||
|
||||
if ($signs) {
|
||||
// настройка парсера для подписей
|
||||
$bbWList = $this->config['p_sig_bbcode'] == '1' ? $bbInfo['forSign'] : [];
|
||||
$bbBList = $this->config['p_sig_img_tag'] == '1' ? [] : ['img'];
|
||||
$bbWList = $this->c->config->p_sig_bbcode == '1' ? $bbInfo['forSign'] : [];
|
||||
$bbBList = $this->c->config->p_sig_img_tag == '1' ? [] : ['img'];
|
||||
$parser->setAttr('isSign', true)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList);
|
||||
|
||||
foreach ($signs as &$cur) {
|
||||
$parser->parse($this->censor($cur));
|
||||
if ($this->config['o_smilies_sig'] == '1' && $user->showSmilies == '1') {
|
||||
$parser->parse($this->c->censorship->censor($cur));
|
||||
if ($this->c->config->o_smilies_sig == '1' && $user->show_smilies == '1') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
$cur = $parser->getHtml();
|
||||
|
@ -405,13 +487,12 @@ class Topic extends Page
|
|||
unset($cur);
|
||||
}
|
||||
|
||||
$topic['subject'] = $this->censor($topic['subject']);
|
||||
$topic['subject'] = $this->c->censorship->censor($topic['subject']);
|
||||
|
||||
$this->onlinePos = 'topic-' . $topic['id'];
|
||||
|
||||
// данные для формы быстрого ответа
|
||||
$form = null;
|
||||
if ($newOn && $this->config['o_quickpost'] == '1') {
|
||||
if ($newOn && $this->c->config->o_quickpost == '1') {
|
||||
$form = [
|
||||
'action' => $this->c->Router->link('NewReply', ['id' => $topic['id']]),
|
||||
'hidden' => [
|
||||
|
@ -439,7 +520,7 @@ class Topic extends Page
|
|||
'type' => 'text',
|
||||
'maxlength' => 80,
|
||||
'title' => __('Email'),
|
||||
'required' => $this->config['p_force_guest_email'] == '1',
|
||||
'required' => $this->c->config->p_force_guest_email == '1',
|
||||
'pattern' => '.+@.+',
|
||||
];
|
||||
}
|
||||
|
@ -449,10 +530,10 @@ class Topic extends Page
|
|||
'title' => __('Message'),
|
||||
'required' => true,
|
||||
'bb' => [
|
||||
['link', __('BBCode'), __($this->config['p_message_bbcode'] == '1' ? 'on' : 'off')],
|
||||
['link', __('url tag'), __($this->config['p_message_bbcode'] == '1' && $user->gPostLinks == '1' ? 'on' : 'off')],
|
||||
['link', __('img tag'), __($this->config['p_message_bbcode'] == '1' && $this->config['p_message_img_tag'] == '1' ? 'on' : 'off')],
|
||||
['link', __('Smilies'), __($this->config['o_smilies'] == '1' ? 'on' : 'off')],
|
||||
['link', __('BBCode'), __($this->c->config->p_message_bbcode == '1' ? 'on' : 'off')],
|
||||
['link', __('url tag'), __($this->c->config->p_message_bbcode == '1' && $user->g_post_links == '1' ? 'on' : 'off')],
|
||||
['link', __('img tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->config->p_message_img_tag == '1' ? 'on' : 'off')],
|
||||
['link', __('Smilies'), __($this->c->config->o_smilies == '1' ? 'on' : 'off')],
|
||||
],
|
||||
];
|
||||
$form['sets'][] = [
|
||||
|
@ -476,26 +557,26 @@ class Topic extends Page
|
|||
}
|
||||
}
|
||||
|
||||
$this->data = [
|
||||
'topic' => $topic,
|
||||
'posts' => $posts,
|
||||
'signs' => $signs,
|
||||
'warnings' => $warnings,
|
||||
'crumbs' => $this->getCrumbs(
|
||||
['Topic', ['id' => $topic['id'], 'name' => $topic['subject']]],
|
||||
[$fDesc, $topic['forum_id']]
|
||||
),
|
||||
'NewReply' => $newOn ? $this->c->Router->link('NewReply', ['id' => $topic['id']]) : $newOn,
|
||||
'stickFP' => $stickFP,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, 'Topic', ['id' => $topic['id'], 'name' => $topic['subject']]),
|
||||
'online' => $this->getUsersOnlineInfo(),
|
||||
'stats' => null,
|
||||
'form' => $form,
|
||||
];
|
||||
$this->nameTpl = 'topic';
|
||||
$this->onlinePos = 'topic-' . $topic['id'];
|
||||
$this->onlineType = true;
|
||||
$this->canonical = $this->c->Router->link('Topic', ['id' => $topic['id'], 'name' => $topic['subject'], 'page' => $page]);
|
||||
$this->topic = $topic;
|
||||
$this->posts = $posts;
|
||||
$this->signs = $signs;
|
||||
$this->warnings = $warnings;
|
||||
$this->crumbs = $this->crumbs(
|
||||
['Topic', ['id' => $topic['id'], 'name' => $topic['subject']]],
|
||||
[$fDesc, $topic['forum_id']]
|
||||
);
|
||||
$this->NewReply = $newOn ? $this->c->Router->link('NewReply', ['id' => $topic['id']]) : $newOn;
|
||||
$this->stickFP = $stickFP;
|
||||
$this->pages = $this->c->Func->paginate($pages, $page, 'Topic', ['id' => $topic['id'], 'name' => $topic['subject']]);
|
||||
$this->online = $this->usersOnlineInfo();
|
||||
$this->stats = null;
|
||||
$this->form = $form;
|
||||
|
||||
$this->canonical = $this->c->Router->link('Topic', ['id' => $topic['id'], 'name' => $topic['subject'], 'page' => $page]);
|
||||
|
||||
if ($this->config['o_topic_views'] == '1') {
|
||||
if ($this->c->config->o_topic_views == '1') {
|
||||
$vars = [
|
||||
':tid' => $topic['id'],
|
||||
];
|
||||
|
@ -512,12 +593,12 @@ class Topic extends Page
|
|||
':visit' => $topic['mt_last_visit'],
|
||||
];
|
||||
$flag = false;
|
||||
$lower = max((int) $user->uMarkAllRead, (int) $topic['mf_mark_all_read'], (int) $topic['mt_last_read']); //????
|
||||
$lower = max((int) $user->u_mark_all_read, (int) $topic['mf_mark_all_read'], (int) $topic['mt_last_read']); //????
|
||||
if ($timeMax > $lower) {
|
||||
$vars[':read'] = $timeMax;
|
||||
$flag = true;
|
||||
}
|
||||
$upper = max($lower, (int) $topic['mt_last_visit'], (int) $user->lastVisit); //????
|
||||
$upper = max($lower, (int) $topic['mt_last_visit'], (int) $user->last_visit); //????
|
||||
if ($topic['last_post'] > $upper) {
|
||||
$vars[':visit'] = $topic['last_post'];
|
||||
$flag = true;
|
||||
|
@ -533,8 +614,8 @@ class Topic extends Page
|
|||
LIMIT 1', $vars);
|
||||
} else {
|
||||
$this->c->DB->exec('UPDATE ::mark_of_topic
|
||||
SET mt_last_visit=?i:visit, mt_last_read=?i:read
|
||||
WHERE uid=?i:uid AND tid=?i:tid', $vars);
|
||||
SET mt_last_visit=?i:visit, mt_last_read=?i:read
|
||||
WHERE uid=?i:uid AND tid=?i:tid', $vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,25 +6,25 @@ 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;
|
||||
}
|
||||
$this->userBanNames = $this->c->bans->userList; //????
|
||||
}
|
||||
|
||||
if(isset($this->userBanNames[$data['username']])) {
|
||||
if (isset($this->userBanNames[mb_strtolower($data['username'])])) { //????
|
||||
return __('Banned');
|
||||
} elseif ($data['title'] != '') {
|
||||
return $data['title'];
|
||||
|
@ -39,7 +39,9 @@ trait UsersTrait
|
|||
|
||||
/**
|
||||
* Определение ссылки на аватарку
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function userGetAvatarLink($id)
|
||||
|
@ -47,10 +49,10 @@ trait UsersTrait
|
|||
$filetypes = array('jpg', 'gif', 'png');
|
||||
|
||||
foreach ($filetypes as $type) {
|
||||
$path = $this->c->DIR_PUBLIC . "/{$this->config['o_avatars_dir']}/{$id}.{$type}";
|
||||
$path = $this->c->DIR_PUBLIC . "/{$this->c->config->o_avatars_dir}/{$id}.{$type}";
|
||||
|
||||
if (file_exists($path) && getimagesize($path)) {
|
||||
return $this->c->PUBLIC_URL . "/{$this->config['o_avatars_dir']}/{$id}.{$type}";
|
||||
return $this->c->PUBLIC_URL . "/{$this->c->config->o_avatars_dir}/{$id}.{$type}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
23
app/Models/SmileyList.php
Normal file
23
app/Models/SmileyList.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class SmileyList extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список смайлов из кеша/БД
|
||||
*
|
||||
* @return SmileyList
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('smilies')) {
|
||||
$this->list = $this->c->Cache->get('smilies');
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
22
app/Models/SmileyList/Load.php
Normal file
22
app/Models/SmileyList/Load.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\SmileyList;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return SmileyList
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$list = $this->c->DB->query('SELECT text, image FROM ::smilies ORDER BY disp_position')->fetchAll(\PDO::FETCH_KEY_PAIR); //???? text уникальное?
|
||||
$this->model->list = $list;
|
||||
$this->c->Cache->set('smilies', $list);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
30
app/Models/Stats.php
Normal file
30
app/Models/Stats.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class Stats extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает статистику из кеша/БД
|
||||
*
|
||||
* @return Stats
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->c->Cache->has('stats')) {
|
||||
$list = $this->c->Cache->get('stats');
|
||||
$this->userTotal = $list['total'];
|
||||
$this->userLast = $list['last'];
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
|
||||
list($topics, $posts) = $this->c->DB->query('SELECT SUM(num_topics), SUM(num_posts) FROM ::forums')->fetch(\PDO::FETCH_NUM);
|
||||
$this->postTotal = $posts;
|
||||
$this->topicTotal = $topics;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
27
app/Models/Stats/Load.php
Normal file
27
app/Models/Stats/Load.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Stats;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
* Создает кеш
|
||||
*
|
||||
* @return Stats
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$total = $this->c->DB->query('SELECT COUNT(id)-1 FROM ::users WHERE group_id!=?i', [$this->c->GROUP_UNVERIFIED])->fetchColumn();
|
||||
$last = $this->c->DB->query('SELECT id, username FROM ::users WHERE group_id!=?i ORDER BY registered DESC LIMIT 1', [$this->c->GROUP_UNVERIFIED])->fetch();
|
||||
$this->model->userTotal = $total;
|
||||
$this->model->userLast = $last;
|
||||
$this->c->Cache->set('stats', [
|
||||
'total' => $total,
|
||||
'last' => $last,
|
||||
]);
|
||||
return $this->model;
|
||||
}
|
||||
}
|
82
app/Models/Stopwords.php
Normal file
82
app/Models/Stopwords.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
class Stopwords extends Model
|
||||
{
|
||||
/**
|
||||
* Загружает список игнорируемых при индексации слов из кеша/БД
|
||||
*
|
||||
* @return Stopwords
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$data = $this->c->Cache->get('stopwords');
|
||||
if (isset($data['id'])
|
||||
&& isset($data['stopwords'])
|
||||
&& $data['id'] === $this->generateId()
|
||||
) {
|
||||
$this->list = $data['stopwords'];
|
||||
} else {
|
||||
$this->load();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует id кэша на основе найденных файлов stopwords.txt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateId()
|
||||
{
|
||||
if (! empty($this->id)) {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
$files = glob($this->c->DIR_LANG . '/*/stopwords.txt');
|
||||
if ($files === false) {
|
||||
return 'cache_id_error';
|
||||
}
|
||||
|
||||
$this->files = $files;
|
||||
$hash = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$hash[] = $file;
|
||||
$hash[] = filemtime($file);
|
||||
}
|
||||
|
||||
return $this->id = sha1(implode('|', $hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регенерация кэша массива слов с возвращением результата
|
||||
*
|
||||
* @return Stopwords
|
||||
*/
|
||||
protected function load()
|
||||
{
|
||||
$id = $this->generateId();
|
||||
|
||||
if (! is_array($this->files)) {
|
||||
$this->list = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
$stopwords = [];
|
||||
foreach ($this->files as $file) {
|
||||
$stopwords = array_merge($stopwords, file($file));
|
||||
}
|
||||
|
||||
// Tidy up and filter the stopwords
|
||||
$stopwords = array_map('trim', $stopwords);
|
||||
$stopwords = array_filter($stopwords);
|
||||
|
||||
$this->c->Cache->set('stopwords', ['id' => $id, 'stopwords' => $stopwords]);
|
||||
$this->list = $stopwords;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -2,22 +2,11 @@
|
|||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\AbstractModel;
|
||||
use ForkBB\Models\DataModel;
|
||||
use ForkBB\Core\Container;
|
||||
|
||||
class User extends AbstractModel
|
||||
class User extends DataModel
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Время
|
||||
* @var int
|
||||
|
@ -26,63 +15,56 @@ class User extends AbstractModel
|
|||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array $data
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(array $data, Container $container)
|
||||
public function __construct(array $data = [], Container $container)
|
||||
{
|
||||
$this->now = time();
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется до конструктора родителя
|
||||
*/
|
||||
protected function beforeConstruct(array $data)
|
||||
{
|
||||
return $data;
|
||||
parent::__construct($data, $container);
|
||||
}
|
||||
|
||||
protected function getIsUnverified()
|
||||
{
|
||||
return $this->groupId == $this->c->GROUP_UNVERIFIED;
|
||||
return $this->group_id == $this->c->GROUP_UNVERIFIED;
|
||||
}
|
||||
|
||||
protected function getIsGuest()
|
||||
{
|
||||
return $this->groupId == $this->c->GROUP_GUEST
|
||||
return $this->group_id == $this->c->GROUP_GUEST
|
||||
|| $this->id < 2
|
||||
|| $this->groupId == $this->c->GROUP_UNVERIFIED;
|
||||
|| $this->group_id == $this->c->GROUP_UNVERIFIED;
|
||||
}
|
||||
|
||||
protected function getIsAdmin()
|
||||
{
|
||||
return $this->groupId == $this->c->GROUP_ADMIN;
|
||||
return $this->group_id == $this->c->GROUP_ADMIN;
|
||||
}
|
||||
|
||||
protected function getIsAdmMod()
|
||||
{
|
||||
return $this->groupId == $this->c->GROUP_ADMIN
|
||||
|| $this->gModerator == '1';
|
||||
return $this->group_id == $this->c->GROUP_ADMIN
|
||||
|| $this->g_moderator == '1';
|
||||
}
|
||||
|
||||
protected function getLogged()
|
||||
{
|
||||
return empty($this->data['logged']) ? $this->now : $this->data['logged'];
|
||||
return empty($this->a['logged']) ? $this->now : $this->a['logged'];
|
||||
}
|
||||
|
||||
protected function getIsLogged()
|
||||
{
|
||||
return ! empty($this->data['logged']);
|
||||
return ! empty($this->a['logged']);
|
||||
}
|
||||
|
||||
protected function getLanguage()
|
||||
{
|
||||
$langs = $this->c->Func->getLangs();
|
||||
|
||||
$lang = $this->isGuest || empty($this->data['language']) || ! in_array($this->data['language'], $langs)
|
||||
? $this->config['o_default_lang']
|
||||
: $this->data['language'];
|
||||
$lang = $this->isGuest || empty($this->a['language']) || ! in_array($this->a['language'], $langs)
|
||||
? $this->c->config->o_default_lang
|
||||
: $this->a['language'];
|
||||
|
||||
if (in_array($lang, $langs)) {
|
||||
return $lang;
|
||||
|
@ -95,9 +77,9 @@ class User extends AbstractModel
|
|||
{
|
||||
$styles = $this->c->Func->getStyles();
|
||||
|
||||
$style = $this->isGuest || empty($this->data['style']) || ! in_array($this->data['style'], $styles)
|
||||
? $this->config['o_default_style']
|
||||
: $this->data['style'];
|
||||
$style = $this->isGuest || empty($this->a['style']) || ! in_array($this->a['style'], $styles)
|
||||
? $this->c->config->o_default_style
|
||||
: $this->a['style'];
|
||||
|
||||
if (in_array($style, $styles)) {
|
||||
return $style;
|
||||
|
|
26
app/Models/User/IsUnique.php
Normal file
26
app/Models/User/IsUnique.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\User;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class IsUnique extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Проверка на уникальность имени пользователя
|
||||
* @param string $username
|
||||
* @return bool
|
||||
*/
|
||||
public function isUnique($username = null)
|
||||
{
|
||||
if (null === $username) {
|
||||
$username = $this->model->username;
|
||||
}
|
||||
$vars = [
|
||||
':name' => $username,
|
||||
':other' => preg_replace('%[^\p{L}\p{N}]%u', '', $username),
|
||||
];
|
||||
$result = $this->c->DB->query('SELECT username FROM ::users WHERE UPPER(username)=UPPER(?s:name) OR UPPER(username)=UPPER(?s:other)', $vars)->fetchAll();
|
||||
return ! count($result);
|
||||
}
|
||||
}
|
46
app/Models/User/Load.php
Normal file
46
app/Models/User/Load.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\User;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Получение пользователя по условию
|
||||
* @param mixed $value
|
||||
* @param string $field
|
||||
* @throws InvalidArgumentException
|
||||
* @return int|User
|
||||
*/
|
||||
public function load($value, $field = 'id')
|
||||
{
|
||||
switch ($field) {
|
||||
case 'id':
|
||||
$where = 'u.id= ?i';
|
||||
break;
|
||||
case 'username':
|
||||
$where = 'u.username= ?s';
|
||||
break;
|
||||
case 'email':
|
||||
$where = 'u.email= ?s';
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Field not supported');
|
||||
}
|
||||
|
||||
$data = $this->c->DB->query('SELECT u.*, g.* FROM ::users AS u LEFT JOIN ::groups AS g ON u.group_id=g.g_id WHERE ' . $where, [$value])
|
||||
->fetchAll();
|
||||
|
||||
// число найденных пользователей отлично от одного
|
||||
if (count($data) !== 1) {
|
||||
return count($data);
|
||||
}
|
||||
// найден гость
|
||||
if ($data[0]['id'] < 2) {
|
||||
return 1;
|
||||
}
|
||||
return $this->model->setAttrs($data[0]);
|
||||
}
|
||||
}
|
|
@ -1,63 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Actions;
|
||||
namespace ForkBB\Models\User;
|
||||
|
||||
use ForkBB\Models\UserCookie;
|
||||
use ForkBB\Models\UserMapper;
|
||||
use ForkBB\Models\MethodModel;
|
||||
use RuntimeException;
|
||||
|
||||
class LoadUserFromCookie
|
||||
class LoadUserFromCookie extends MethodModel
|
||||
{
|
||||
protected $mapper;
|
||||
protected $cookie;
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param UserMapper $mapper
|
||||
* @param UserCookie $cookie
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(UserMapper $mapper, UserCookie $cookie, array $config)
|
||||
{
|
||||
$this->mapper = $mapper;
|
||||
$this->cookie = $cookie;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение юзера на основе куки авторизации
|
||||
* Обновление куки аутентификации
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function load()
|
||||
public function loadCurrent()
|
||||
{
|
||||
$id = $this->cookie->id() ?: 1;
|
||||
$user = $this->mapper->getCurrent($id);
|
||||
$cookie = $this->c->Cookie;
|
||||
$this->loadUser((int) $cookie->uId);
|
||||
|
||||
if (! $user->isGuest) {
|
||||
if (! $this->cookie->verifyHash($user->id, $user->password)) {
|
||||
$user = $this->mapper->getCurrent(1);
|
||||
} elseif ($this->config['o_check_ip'] == '1'
|
||||
&& $user->isAdmMod
|
||||
&& $user->registrationIp != $user->ip
|
||||
if (! $this->model->isGuest) {
|
||||
if (! $cookie->verifyUser($this->model)) {
|
||||
$this->model = $this->loadUser(1);
|
||||
} elseif ($this->c->config->o_check_ip == '1'
|
||||
&& $this->model->isAdmMod
|
||||
&& $this->model->registration_ip != $this->model->ip
|
||||
) {
|
||||
$user = $this->mapper->getCurrent(1);
|
||||
$this->model = $this->loadUser(1);
|
||||
}
|
||||
}
|
||||
|
||||
$this->cookie->setUserCookie($user->id, $user->password);
|
||||
$cookie->setUser($this->model);
|
||||
|
||||
if ($user->isGuest) {
|
||||
$user->isBot = $this->isBot();
|
||||
$user->dispTopics = $this->config['o_disp_topics_default'];
|
||||
$user->dispPosts = $this->config['o_disp_posts_default'];
|
||||
$user->timezone = $this->config['o_default_timezone'];
|
||||
$user->dst = $this->config['o_default_dst'];
|
||||
$user->language = $this->config['o_default_lang'];
|
||||
$user->style = $this->config['o_default_style'];
|
||||
if ($this->model->isGuest) {
|
||||
$this->model->__isBot = $this->isBot();
|
||||
$this->model->__disp_topics = $this->c->config->o_disp_topics_default;
|
||||
$this->model->__disp_posts = $this->c->config->o_disp_posts_default;
|
||||
$this->model->__timezone = $this->c->config->o_default_timezone;
|
||||
$this->model->__dst = $this->c->config->o_default_dst;
|
||||
# $this->model->language = $this->c->config->o_default_lang;
|
||||
# $this->model->style = $this->c->config->o_default_style;
|
||||
|
||||
// быстрое переключение языка - Visman
|
||||
/* $language = $this->cookie->get('glang');
|
||||
|
@ -65,30 +46,64 @@ class LoadUserFromCookie
|
|||
$language = preg_replace('%[^a-zA-Z0-9_]%', '', $language);
|
||||
$languages = forum_list_langs();
|
||||
if (in_array($language, $languages)) {
|
||||
$user->language = $language;
|
||||
$this->model->language = $language;
|
||||
}
|
||||
} */
|
||||
} else {
|
||||
$user->isBot = false;
|
||||
if (! $user->dispTopics) {
|
||||
$user->dispTopics = $this->config['o_disp_topics_default'];
|
||||
$this->model->__isBot = false;
|
||||
if (! $this->model->disp_topics) {
|
||||
$this->model->__disp_topics = $this->c->config->o_disp_topics_default;
|
||||
}
|
||||
if (! $user->dispPosts) {
|
||||
$user->dispPosts = $this->config['o_disp_posts_default'];
|
||||
if (! $this->model->disp_posts) {
|
||||
$this->model->__disp_posts = $this->c->config->o_disp_posts_default;
|
||||
}
|
||||
// Special case: We've timed out, but no other user has browsed the forums since we timed out
|
||||
if ($user->isLogged && $user->logged < time() - $this->config['o_timeout_visit']) {
|
||||
$this->mapper->updateLastVisit($user);
|
||||
$user->lastVisit = $user->logged;
|
||||
if ($this->model->isLogged && $this->model->logged < time() - $this->c->config->o_timeout_visit) {
|
||||
$this->model->updateLastVisit();
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузка данных в модель пользователя из базы
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function loadUser($id)
|
||||
{
|
||||
$data = null;
|
||||
$ip = $this->getIp();
|
||||
if ($id > 1) {
|
||||
$data = $this->c->DB->query('SELECT u.*, g.*, o.logged, o.idle FROM ::users AS u INNER JOIN ::groups AS g ON u.group_id=g.g_id LEFT JOIN ::online AS o ON o.user_id=u.id WHERE u.id=?i:id', [':id' => $id])->fetch();
|
||||
}
|
||||
if (empty($data['id'])) {
|
||||
$data = $this->c->DB->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM ::users AS u INNER JOIN ::groups AS g ON u.group_id=g.g_id LEFT JOIN ::online AS o ON (o.user_id=1 AND o.ident=?s:ip) WHERE u.id=1', [':ip' => $ip])->fetch();
|
||||
}
|
||||
if (empty($data['id'])) {
|
||||
throw new RuntimeException('Unable to fetch guest information. Your database must contain both a guest user and a guest user group.');
|
||||
}
|
||||
$this->model->setAttrs($data);
|
||||
$this->model->__ip = $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возврат ip пользователя
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getIp()
|
||||
{
|
||||
return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?: 'unknow';
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на робота
|
||||
* Если робот, то возврат имени
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
protected function isBot()
|
||||
|
@ -125,9 +140,11 @@ class LoadUserFromCookie
|
|||
|
||||
/**
|
||||
* Выделяет имя робота из юзерагента
|
||||
*
|
||||
* @param string $agent
|
||||
* @param string $agentL
|
||||
* @retrun string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function nameBot($agent, $agentL)
|
||||
{
|
71
app/Models/User/Save.php
Normal file
71
app/Models/User/Save.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\User;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
use RuntimeException;
|
||||
|
||||
class Save extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Обновляет данные пользователя
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
if (empty($this->model->id)) {
|
||||
throw new RuntimeException('The model does not have ID');
|
||||
}
|
||||
$modified = $this->model->getModified();
|
||||
if (empty($modified)) {
|
||||
return;
|
||||
}
|
||||
$values = $this->model->getAttrs();
|
||||
$fileds = $this->c->dbMap->users;
|
||||
$set = $vars = [];
|
||||
foreach ($modified as $name) {
|
||||
if (! isset($fileds[$name])) {
|
||||
continue;
|
||||
}
|
||||
$vars[] = $values[$name];
|
||||
$set[] = $name . '=?' . $fileds[$name];
|
||||
}
|
||||
if (empty($set)) {
|
||||
return;
|
||||
}
|
||||
$vars[] = $this->model->id;
|
||||
$this->c->DB->query('UPDATE ::users SET ' . implode(', ', $set) . ' WHERE id=?i', $vars);
|
||||
$this->model->resModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет новую запись в таблицу пользователей
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function insert()
|
||||
{
|
||||
$modified = $this->model->getModified();
|
||||
if (null !== $this->model->id || in_array('id', $modified)) {
|
||||
throw new RuntimeException('The model has ID');
|
||||
}
|
||||
$values = $this->model->getAttrs();
|
||||
$fileds = $this->c->dbMap->users;
|
||||
$set = $set2 = $vars = [];
|
||||
foreach ($modified as $name) {
|
||||
if (! isset($fileds[$name])) {
|
||||
continue;
|
||||
}
|
||||
$vars[] = $values[$name];
|
||||
$set[] = $name;
|
||||
$set2[] = '?' . $fileds[$name];
|
||||
}
|
||||
if (empty($set)) {
|
||||
return;
|
||||
}
|
||||
$this->c->DB->query('INSERT INTO ::users (' . implode(', ', $set) . ') VALUES (' . implode(', ', $set2) . ')', $vars);
|
||||
$this->model->resModified();
|
||||
return $this->c->DB->lastInsertId();
|
||||
}
|
||||
}
|
19
app/Models/User/UpdateLastVisit.php
Normal file
19
app/Models/User/UpdateLastVisit.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\User;
|
||||
|
||||
use ForkBB\Models\MethodModel;
|
||||
|
||||
class UpdateLastVisit extends MethodModel
|
||||
{
|
||||
/**
|
||||
* Обновляет время последнего визита для конкретного пользователя
|
||||
*/
|
||||
public function updateLastVisit()
|
||||
{
|
||||
if ($this->model->isLogged) {
|
||||
$this->c->DB->exec('UPDATE ::users SET last_visit=?i:loggid WHERE id=?i:id', [':loggid' => $this->model->logged, ':id' => $this->model->id]);
|
||||
$this->model->__last_visit = $this->model->logged;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Cookie;
|
||||
use ForkBB\Core\Secury;
|
||||
|
||||
class UserCookie extends Cookie
|
||||
{
|
||||
const NAME = 'user';
|
||||
const KEY1 = 'key1';
|
||||
const KEY2 = 'key2';
|
||||
|
||||
/**
|
||||
* Флаг указывающий на режим "запомнить меня"
|
||||
* @var bool
|
||||
*/
|
||||
protected $remember;
|
||||
|
||||
/**
|
||||
* Номер юзера из куки аутентификации
|
||||
* @var int
|
||||
*/
|
||||
protected $uId;
|
||||
|
||||
/**
|
||||
* Время "протухания" куки аутентификации
|
||||
* @var int
|
||||
*/
|
||||
protected $expTime;
|
||||
|
||||
/**
|
||||
* Хэш хэша пароля юзера из куки аутентификации
|
||||
* @var string
|
||||
*/
|
||||
protected $passHash;
|
||||
|
||||
/**
|
||||
* Время жизни куки без запоминания
|
||||
* @var int
|
||||
*/
|
||||
protected $min;
|
||||
|
||||
/**
|
||||
* Время жизни куки с запоминанием
|
||||
* @var int
|
||||
*/
|
||||
protected $max;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param Secury $secury
|
||||
* @param array $options
|
||||
* @param int $min
|
||||
* @param int $max
|
||||
*/
|
||||
public function __construct(Secury $secury, array $options, $min, $max)
|
||||
{
|
||||
parent::__construct($secury, $options);
|
||||
$this->min = (int) $min;
|
||||
$this->max = (int) $max;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Выделение данных из куки аутентификации
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
$ckUser = $this->get(self::NAME);
|
||||
|
||||
if (null === $ckUser
|
||||
|| ! preg_match('%^(\-)?(\d{1,10})_(\d{10})_([a-f\d]{32,})_([a-f\d]{32,})$%Di', $ckUser, $ms)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (2 > $ms[2]
|
||||
|| time() > $ms[3]
|
||||
|| ! hash_equals($this->secury->hmac($ms[1] . $ms[2] . $ms[3] . $ms[4], self::KEY1), $ms[5])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->remember = empty($ms[1]);
|
||||
$this->uId = (int) $ms[2];
|
||||
$this->expTime = (int) $ms[3];
|
||||
$this->passHash = $ms[4];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает id юзера из куки
|
||||
* @return int|false
|
||||
*/
|
||||
public function id()
|
||||
{
|
||||
return $this->uId ?: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка хэша пароля
|
||||
* @param int $id
|
||||
* @param string $hash
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyHash($id, $hash)
|
||||
{
|
||||
return $this->uId === (int) $id
|
||||
&& hash_equals($this->passHash, $this->secury->hmac($hash . $this->expTime, self::KEY2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Установка куки аутентификации юзера
|
||||
* @param int $id
|
||||
* @param string $hash
|
||||
* @param bool $remember
|
||||
* @return bool
|
||||
*/
|
||||
public function setUserCookie($id, $hash, $remember = null)
|
||||
{
|
||||
if ($id < 2) {
|
||||
return $this->deleteUserCookie();
|
||||
}
|
||||
|
||||
if ($remember
|
||||
|| (null === $remember
|
||||
&& $this->uId === (int) $id
|
||||
&& $this->remember
|
||||
)
|
||||
) {
|
||||
$expTime = time() + $this->max;
|
||||
$expire = $expTime;
|
||||
$pfx = '';
|
||||
} else {
|
||||
$expTime = time() + $this->min;
|
||||
$expire = 0;
|
||||
$pfx = '-';
|
||||
}
|
||||
$passHash = $this->secury->hmac($hash . $expTime, self::KEY2);
|
||||
$ckHash = $this->secury->hmac($pfx . $id . $expTime . $passHash, self::KEY1);
|
||||
|
||||
return $this->set(self::NAME, $pfx . $id . '_' . $expTime . '_' . $passHash . '_' . $ckHash, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление куки аутентификации юзера
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteUserCookie()
|
||||
{
|
||||
if (null === $this->get(self::NAME)) {
|
||||
return true;
|
||||
} else {
|
||||
return $this->delete(self::NAME);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\User;
|
||||
use RuntimeException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class UserMapper
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
$this->config = $container->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возврат адреса пользователя
|
||||
* @return string
|
||||
*/
|
||||
protected function getIpAddress()
|
||||
{
|
||||
return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?: 'unknow';
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение данных для текущего пользователя/гостя
|
||||
* @param int $id
|
||||
* @return User
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getCurrent($id = 1)
|
||||
{
|
||||
$ip = $this->getIpAddress();
|
||||
$user = null;
|
||||
if ($id > 1) {
|
||||
$user = $this->c->DB->query('SELECT u.*, g.*, o.logged, o.idle FROM ::users AS u INNER JOIN ::groups AS g ON u.group_id=g.g_id LEFT JOIN ::online AS o ON o.user_id=u.id WHERE u.id=?i:id', [':id' => $id])->fetch();
|
||||
}
|
||||
if (empty($user['id'])) {
|
||||
$user = $this->c->DB->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM ::users AS u INNER JOIN ::groups AS g ON u.group_id=g.g_id LEFT JOIN ::online AS o ON (o.user_id=1 AND o.ident=?s:ip) WHERE u.id=1', [':ip' => $ip])->fetch();
|
||||
}
|
||||
if (empty($user['id'])) {
|
||||
throw new RuntimeException('Unable to fetch guest information. Your database must contain both a guest user and a guest user group.');
|
||||
}
|
||||
$user['ip'] = $ip;
|
||||
return new User($user, $this->c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет время последнего визита для конкретного пользователя
|
||||
* @param User $user
|
||||
*/
|
||||
public function updateLastVisit(User $user)
|
||||
{
|
||||
if ($user->isLogged) {
|
||||
$this->c->DB->exec('UPDATE ::users SET last_visit=?i:loggid WHERE id=?i:id', [':loggid' => $user->logged, ':id' => $user->id]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение пользователя по условию
|
||||
* @param int|string
|
||||
* @param string $field
|
||||
* @return int|User
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function getUser($value, $field = 'id')
|
||||
{
|
||||
switch ($field) {
|
||||
case 'id':
|
||||
$where = 'u.id= ?i';
|
||||
break;
|
||||
case 'username':
|
||||
$where = 'u.username= ?s';
|
||||
break;
|
||||
case 'email':
|
||||
$where = 'u.email= ?s';
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Field not supported');
|
||||
}
|
||||
$result = $this->c->DB->query('SELECT u.*, g.* FROM ::users AS u LEFT JOIN ::groups AS g ON u.group_id=g.g_id WHERE ' . $where, [$value])->fetchAll();
|
||||
// найдено несколько пользователей
|
||||
if (count($result) !== 1) {
|
||||
return count($result);
|
||||
}
|
||||
// найден гость
|
||||
if ($result[0]['id'] == 1) {
|
||||
return 1;
|
||||
}
|
||||
return new User($result[0], $this->c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на уникальность имени пользователя
|
||||
* @param string $username
|
||||
* @return bool
|
||||
*/
|
||||
public function isUnique($username)
|
||||
{
|
||||
$vars = [
|
||||
':name' => $username,
|
||||
':other' => preg_replace('%[^\p{L}\p{N}]%u', '', $username),
|
||||
];
|
||||
$result = $this->c->DB->query('SELECT username FROM ::users WHERE UPPER(username)=UPPER(?s:name) OR UPPER(username)=UPPER(?s:other)', $vars)->fetchAll();
|
||||
return ! count($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновить данные пользователя
|
||||
* @param int $id
|
||||
* @param array $update
|
||||
*/
|
||||
public function updateUser($id, array $update)
|
||||
{
|
||||
$id = (int) $id;
|
||||
if ($id < 2 || empty($update)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$set = $vars = [];
|
||||
foreach ($update as $field => $value) {
|
||||
$vars[] = $value;
|
||||
if (is_int($value)) {
|
||||
$set[] = $field . ' = ?i';
|
||||
} else {
|
||||
$set[] = $field . ' = ?s';
|
||||
}
|
||||
}
|
||||
$vars[] = $id;
|
||||
$this->c->DB->query('UPDATE ::users SET ' . implode(', ', $set) . ' WHERE id=?i', $vars); //????
|
||||
}
|
||||
|
||||
/**
|
||||
* Создание нового пользователя
|
||||
* @param User $user
|
||||
* @throws
|
||||
* @return int
|
||||
*/
|
||||
public function newUser(User $user)
|
||||
{
|
||||
$vars = [
|
||||
':name' => $user->username,
|
||||
':group' => $user->groupId,
|
||||
':password' => $user->password,
|
||||
':email' => $user->email,
|
||||
':confirmed' => $user->emailConfirmed,
|
||||
':setting' => $this->config['o_default_email_setting'],
|
||||
':timezone' => $this->config['o_default_timezone'],
|
||||
':dst' => $this->config['o_default_dst'],
|
||||
':language' => $user->language,
|
||||
':style' => $user->style,
|
||||
':registered' => time(),
|
||||
':ip' => $this->getIpAddress(),
|
||||
':activate' => $user->activateString,
|
||||
':mark' => $user->uMarkAllRead,
|
||||
];
|
||||
$this->c->DB->query('INSERT INTO ::users (username, group_id, password, email, email_confirmed, email_setting, timezone, dst, language, style, registered, registration_ip, activate_string, u_mark_all_read) VALUES(?s:name, ?i:group, ?s:password, ?s:email, ?i:confirmed, ?i:setting, ?s:timezone, ?i:dst, ?s:language, ?s:style, ?i:registered, ?s:ip, ?s:activate, ?i:mark)', $vars);
|
||||
return $this->c->DB->lastInsertId();
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
namespace ForkBB;
|
||||
|
||||
use ForkBB\Core\Container;
|
||||
use ForkBB\Models\Pages\Page;
|
||||
use ForkBB\Models\Page;
|
||||
use RuntimeException;
|
||||
|
||||
// боевой
|
||||
|
@ -47,8 +47,8 @@ $c->DIR_CONFIG = __DIR__ . '/config';
|
|||
$c->DIR_CACHE = __DIR__ . '/cache';
|
||||
$c->DIR_VIEWS = __DIR__ . '/templates';
|
||||
$c->DIR_LANG = __DIR__ . '/lang';
|
||||
$c->DATE_FORMATS = [$c->config['o_date_format'], 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y'];
|
||||
$c->TIME_FORMATS = [$c->config['o_time_format'], 'H:i:s', 'H:i', 'g:i:s a', 'g:i a'];
|
||||
$c->DATE_FORMATS = [$c->config->o_date_format, 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y'];
|
||||
$c->TIME_FORMATS = [$c->config->o_time_format, 'H:i:s', 'H:i', 'g:i:s a', 'g:i a'];
|
||||
|
||||
$controllers = ['Routing', 'Primary'];
|
||||
$page = null;
|
||||
|
@ -56,13 +56,12 @@ while (! $page instanceof Page && $cur = array_pop($controllers)) {
|
|||
$page = $c->$cur;
|
||||
}
|
||||
|
||||
if ($page->getDataForOnline(true)) {
|
||||
$c->Online->handle($page);
|
||||
if (null !== $page->onlinePos) {
|
||||
$c->Online->calc($page);
|
||||
}
|
||||
$tpl = $c->View->rendering($page);
|
||||
if ($tpl !== null && $c->DEBUG > 0) {
|
||||
$debug = $c->Debug->debug();
|
||||
$debug = $c->View->rendering($debug);
|
||||
$debug = $c->View->rendering($c->Debug->debug());
|
||||
$tpl = str_replace('<!-- debuginfo -->', $debug, $tpl);
|
||||
}
|
||||
exit($tpl);
|
||||
|
|
|
@ -79,13 +79,13 @@ msgid "Ban message"
|
|||
msgstr "You are banned from this forum."
|
||||
|
||||
msgid "Ban message 2"
|
||||
msgstr "The ban expires at the end of"
|
||||
msgstr "The ban expires at the end of %s"
|
||||
|
||||
msgid "Ban message 3"
|
||||
msgstr "The administrator or moderator that banned you left the following message:"
|
||||
|
||||
msgid "Ban message 4"
|
||||
msgstr "Please direct any inquiries to the forum administrator at"
|
||||
msgstr "Please direct any inquiries to the forum administrator at <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
|
||||
msgid "Never"
|
||||
msgstr "Never"
|
||||
|
|
|
@ -79,13 +79,13 @@ msgid "Ban message"
|
|||
msgstr "Ваша учетная запись заблокирована."
|
||||
|
||||
msgid "Ban message 2"
|
||||
msgstr "Блокировка заканчивается"
|
||||
msgstr "Блокировка заканчивается %s"
|
||||
|
||||
msgid "Ban message 3"
|
||||
msgstr "Причина блокирования:"
|
||||
msgstr "Администратор или модератор, установивший блокировку, оставил следующее сообщение:"
|
||||
|
||||
msgid "Ban message 4"
|
||||
msgstr "Все возникшие вопросы отправляйте администратору форума по адресу"
|
||||
msgstr "Все возникшие вопросы отправляйте администратору форума по адресу <a href=\"mailto:%1$s\">%1$s</a>."
|
||||
|
||||
msgid "Never"
|
||||
msgstr "Нет"
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
<section class="f-admin">
|
||||
<h2>{!! __('Group settings head') !!}</h2>
|
||||
<div class="f-fdiv">
|
||||
<form class="f-form" method="post" action="{!! $formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $formToken !!}">
|
||||
<form class="f-form" method="post" action="{!! $p->formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $p->formToken !!}">
|
||||
<dl>
|
||||
@foreach($form as $key => $cur)
|
||||
@foreach($p->form as $key => $cur)
|
||||
<dt>{!! $cur['title'] !!}</dt>
|
||||
<dd>
|
||||
@if($cur['type'] == 'text')
|
||||
<input class="f-ctrl" @if(isset($cur['required'])){!! 'required' !!}@endif type="text" name="{{ $key }}" maxlength="{!! $cur['maxlength'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$tabindex !!}">
|
||||
<input class="f-ctrl" @if(isset($cur['required'])){!! 'required' !!}@endif type="text" name="{{ $key }}" maxlength="{!! $cur['maxlength'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$p->tabindex !!}">
|
||||
@elseif($cur['type'] == 'number')
|
||||
<input class="f-ctrl" type="number" name="{{ $key }}" min="{!! $cur['min'] !!}" max="{!! $cur['max'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$tabindex !!}">
|
||||
<input class="f-ctrl" type="number" name="{{ $key }}" min="{!! $cur['min'] !!}" max="{!! $cur['max'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$p->tabindex !!}">
|
||||
@elseif($cur['type'] == 'select')
|
||||
<select class="f-ctrl" name="{{ $key }}" tabindex="{!! ++$tabindex !!}">
|
||||
<select class="f-ctrl" name="{{ $key }}" tabindex="{!! ++$p->tabindex !!}">
|
||||
@foreach($cur['options'] as $v => $n)
|
||||
@if($v == $cur['value'])
|
||||
<option value="{{ $v }}" selected>{{ $n }}</option>
|
||||
|
@ -25,9 +25,9 @@
|
|||
@elseif($cur['type'] == 'radio')
|
||||
@foreach($cur['values'] as $v => $n)
|
||||
@if($v == $cur['value'])
|
||||
<label class="f-label"><input type="radio" name="{{ $key }}" value="{{ $v }}" checked tabindex="{!! ++$tabindex !!}">{{ $n }}</label>
|
||||
<label class="f-label"><input type="radio" name="{{ $key }}" value="{{ $v }}" checked tabindex="{!! ++$p->tabindex !!}">{{ $n }}</label>
|
||||
@else
|
||||
<label class="f-label"><input type="radio" name="{{ $key }}" value="{{ $v }}" tabindex="{!! ++$tabindex !!}">{{ $n }}</label>
|
||||
<label class="f-label"><input type="radio" name="{{ $key }}" value="{{ $v }}" tabindex="{!! ++$p->tabindex !!}">{{ $n }}</label>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
|
@ -37,11 +37,11 @@
|
|||
</dd>
|
||||
@endforeach
|
||||
</dl>
|
||||
@if($warn)
|
||||
<p class="f-finfo">{!! $warn !!}</p>
|
||||
@if($p->warn)
|
||||
<p class="f-finfo">{!! $p->warn !!}</p>
|
||||
@endif
|
||||
<div>
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$tabindex !!}">
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$p->tabindex !!}">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<section class="f-admin">
|
||||
<h2>{!! __('Add group subhead') !!}</h2>
|
||||
<div class="f-fdiv">
|
||||
<form class="f-form" method="post" action="{!! $formActionNew !!}">
|
||||
<input type="hidden" name="token" value="{!! $formTokenNew !!}">
|
||||
<form class="f-form" method="post" action="{!! $p->formActionNew !!}">
|
||||
<input type="hidden" name="token" value="{!! $p->formTokenNew !!}">
|
||||
<dl>
|
||||
<dt>{!! __('New group label') !!}</dt>
|
||||
<dd>
|
||||
<select class="f-ctrl" id="id-basegroup" name="basegroup" tabindex="{!! ++$tabindex !!}">
|
||||
@foreach($groupsNew as $cur)
|
||||
@if ($cur[0] == $defaultGroup)
|
||||
<select class="f-ctrl" id="id-basegroup" name="basegroup" tabindex="{!! ++$p->tabindex !!}">
|
||||
@foreach($p->groupsNew as $cur)
|
||||
@if ($cur[0] == $p->defaultGroup)
|
||||
<option value="{!! $cur[0] !!}" selected>{{ $cur[1] }}</option>
|
||||
@else
|
||||
<option value="{!! $cur[0] !!}">{{ $cur[1] }}</option>
|
||||
|
@ -20,7 +20,7 @@
|
|||
</dd>
|
||||
</dl>
|
||||
<div>
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Add') !!}" tabindex="{!! ++$tabindex !!}">
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Add') !!}" tabindex="{!! ++$p->tabindex !!}">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -28,14 +28,14 @@
|
|||
<section class="f-admin">
|
||||
<h2>{!! __('Default group subhead') !!}</h2>
|
||||
<div class="f-fdiv">
|
||||
<form class="f-form" method="post" action="{!! $formActionDefault !!}">
|
||||
<input type="hidden" name="token" value="{!! $formTokenDefault !!}">
|
||||
<form class="f-form" method="post" action="{!! $p->formActionDefault !!}">
|
||||
<input type="hidden" name="token" value="{!! $p->formTokenDefault !!}">
|
||||
<dl>
|
||||
<dt>{!! __('Default group label') !!}</dt>
|
||||
<dd>
|
||||
<select class="f-ctrl" id="id-defaultgroup" name="defaultgroup" tabindex="{!! ++$tabindex !!}">
|
||||
@foreach($groupsDefault as $cur)
|
||||
@if ($cur[0] == $defaultGroup)
|
||||
<select class="f-ctrl" id="id-defaultgroup" name="defaultgroup" tabindex="{!! ++$p->tabindex !!}">
|
||||
@foreach($p->groupsDefault as $cur)
|
||||
@if ($cur[0] == $p->defaultGroup)
|
||||
<option value="{!! $cur[0] !!}" selected>{{ $cur[1] }}</option>
|
||||
@else
|
||||
<option value="{!! $cur[0] !!}">{{ $cur[1] }}</option>
|
||||
|
@ -46,7 +46,7 @@
|
|||
</dd>
|
||||
</dl>
|
||||
<div>
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$tabindex !!}">
|
||||
<input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$p->tabindex !!}">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -56,11 +56,11 @@
|
|||
<div>
|
||||
<p>{!! __('Edit groups info') !!}</p>
|
||||
<ol class="f-grlist">
|
||||
@foreach($groupsList as $cur)
|
||||
@foreach($p->groupsList as $cur)
|
||||
<li>
|
||||
<a href="{!! $cur[0] !!}" tabindex="{!! ++$tabindex !!}">{{ $cur[1] }}</a>
|
||||
<a href="{!! $cur[0] !!}" tabindex="{!! ++$p->tabindex !!}">{{ $cur[1] }}</a>
|
||||
@if($cur[2])
|
||||
<a class="f-btn" href="{!! $cur[2] !!}" tabindex="{!! ++$tabindex !!}">{!! __('Delete link') !!}</a>
|
||||
<a class="f-btn" href="{!! $cur[2] !!}" tabindex="{!! ++$p->tabindex !!}">{!! __('Delete link') !!}</a>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
<div>
|
||||
<dl>
|
||||
<dt>{!! __('ForkBB version label') !!}</dt>
|
||||
<dd>{!! __('ForkBB version data', $revision) !!}</dd>
|
||||
<dd>{!! __('ForkBB version data', $p->revision) !!}</dd>
|
||||
<dt>{!! __('Server statistics label') !!}</dt>
|
||||
<dd><a href="{!! $linkStat !!}">{!! __('View server statistics') !!}</a></dd>
|
||||
<dd><a href="{!! $p->linkStat !!}">{!! __('View server statistics') !!}</a></dd>
|
||||
<dt>{!! __('Support label') !!}</dt>
|
||||
<dd><a href="https://github.com/forkbb/forkbb">GitHub</a></dd>
|
||||
</dl>
|
||||
|
|
|
@ -4,24 +4,24 @@
|
|||
<div>
|
||||
<dl>
|
||||
<dt>{!! __('Server load label') !!}</dt>
|
||||
<dd>{!! __('Server load data', $serverLoad, $numOnline) !!}</dd>
|
||||
@if($isAdmin)
|
||||
<dd>{!! __('Server load data', $p->serverLoad, $p->numOnline) !!}</dd>
|
||||
@if($p->isAdmin)
|
||||
<dt>{!! __('Environment label') !!}</dt>
|
||||
<dd>
|
||||
{!! __('Environment data OS', PHP_OS) !!}<br>
|
||||
{!! __('Environment data version', phpversion(), '<a href="' . $linkInfo . '">'.__('Show info').'</a>') !!}<br>
|
||||
{!! __('Environment data acc', $accelerator) !!}
|
||||
{!! __('Environment data version', phpversion(), '<a href="' . $p->linkInfo . '">'.__('Show info').'</a>') !!}<br>
|
||||
{!! __('Environment data acc', $p->accelerator) !!}
|
||||
</dd>
|
||||
<dt>{!! __('Database label') !!}</dt>
|
||||
<dd>
|
||||
{{ $dbVersion }}
|
||||
@if($tRecords && $tSize)
|
||||
<br>{!! __('Database data rows', $tRecords) !!}
|
||||
<br>{!! __('Database data size', $tSize) !!}
|
||||
{{ $p->dbVersion }}
|
||||
@if($p->tRecords && $p->tSize)
|
||||
<br>{!! __('Database data rows', $p->tRecords) !!}
|
||||
<br>{!! __('Database data size', $p->tSize) !!}
|
||||
@endif
|
||||
@if($tOther)
|
||||
@if($p->tOther)
|
||||
<br><br>{!! __('Other')!!}
|
||||
@foreach($tOther as $key => $value)
|
||||
@foreach($p->tOther as $key => $value)
|
||||
<br>{{ $key }} = {{ $value }}
|
||||
@endforeach
|
||||
@endif
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<section class="f-main f-message">
|
||||
<h2>{{ __('Info') }}</h2>
|
||||
<p>{!! __('Ban message') !!}</p>
|
||||
@if(! empty($banned['expire']))
|
||||
<p>{!! __('Ban message 2') !!} {{ $banned['expire'] }}</p>
|
||||
@if(! empty($p->ban['expire']))
|
||||
<p>{!! __('Ban message 2', $p->ban['expire']) !!}</p>
|
||||
@endif
|
||||
@if(! empty($banned['message']))
|
||||
@if(! empty($p->ban['message']))
|
||||
<p>{!! __('Ban message 3') !!}</p>
|
||||
<p><strong>{{ $banned['message'] }}</strong></p>
|
||||
<p><strong>{{ $p->ban['message'] }}</strong></p>
|
||||
@endif
|
||||
<p>{!! __('Ban message 4'] !!) <a href="mailto:{{ $adminEmail }}">{{ $adminEmail }}</a>.</p>
|
||||
<p>{!! __('Ban message 4', $p->adminEmail, $p->adminEmail) !!}</p>
|
||||
</section>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<section class="f-main f-login">
|
||||
<div class="f-fdiv f-lrdiv">
|
||||
<h2>{!! __('Change pass') !!}</h2>
|
||||
<form class="f-form" method="post" action="{!! $formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $formToken !!}">
|
||||
<form class="f-form" method="post" action="{!! $p->formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $p->formToken !!}">
|
||||
<fieldset>
|
||||
<dl>
|
||||
<dt><label class="f-child1 f-req" for="id-password">{!! __('New pass') !!}</label></dt>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@section('crumbs')
|
||||
<ul class="f-crumbs">
|
||||
@foreach($crumbs as $cur)
|
||||
@foreach($p->crumbs as $cur)
|
||||
@if($cur[2])
|
||||
<li class="f-crumb"><a href="{!! $cur[0] !!}" class="active">{{ $cur[1] }}</a></li>
|
||||
@else
|
||||
|
@ -10,15 +10,15 @@
|
|||
</ul>
|
||||
@endsection
|
||||
@section('linkpost')
|
||||
@if($newTopic)
|
||||
@if($p->newTopic)
|
||||
<div class="f-link-post">
|
||||
<a class="f-btn" href="{!! $newTopic !!}">{!! __('Post topic') !!}</a>
|
||||
<a class="f-btn" href="{!! $p->newTopic !!}">{!! __('Post topic') !!}</a>
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
||||
@section('pages')
|
||||
<nav class="f-pages">
|
||||
@foreach($pages as $cur)
|
||||
@foreach($p->pages as $cur)
|
||||
@if($cur[2])
|
||||
<span class="f-page active">{{ $cur[1] }}</span>
|
||||
@elseif($cur[1] === 'space')
|
||||
|
@ -34,13 +34,13 @@
|
|||
</nav>
|
||||
@endsection
|
||||
@extends('layouts/main')
|
||||
@if($forums)
|
||||
@if($p->forums)
|
||||
<div class="f-nav-links">
|
||||
@yield('crumbs')
|
||||
</div>
|
||||
<section class="f-subforums">
|
||||
<ol class="f-ftlist">
|
||||
@foreach($forums as $id => $cat)
|
||||
@foreach($p->forums as $id => $cat)
|
||||
<li id="id-subforums{!! $id !!}" class="f-category">
|
||||
<h2>{{ __('Sub forum', 2) }}</h2>
|
||||
<ol class="f-table">
|
||||
|
@ -58,20 +58,20 @@
|
|||
@endif
|
||||
<div class="f-nav-links">
|
||||
@yield('crumbs')
|
||||
@if($newTopic || $pages)
|
||||
@if($p->newTopic || $p->pages)
|
||||
<div class="f-links-b clearfix">
|
||||
@yield('pages')
|
||||
@yield('linkpost')
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if(empty($topics))
|
||||
@if(!$p->topics)
|
||||
<section class="f-main f-message">
|
||||
<h2>{!! __('Empty forum') !!}</h2>
|
||||
</section>
|
||||
@else
|
||||
<section class="f-main f-forum">
|
||||
<h2>{{ $forumName }}</h2>
|
||||
<h2>{{ $p->forumName }}</h2>
|
||||
<div class="f-ftlist">
|
||||
<ol class="f-table">
|
||||
<li class="f-row f-thead" value="0">
|
||||
|
@ -79,7 +79,7 @@
|
|||
<div class="f-hcell f-cstats">{!! __('Stats') !!}</div>
|
||||
<div class="f-hcell f-clast">{!! __('Last post') !!}</div>
|
||||
</li>
|
||||
@foreach($topics as $topic)
|
||||
@foreach($p->topics as $topic)
|
||||
@if($topic['moved_to'])
|
||||
<li id="topic-{!! $topic['id']!!}" class="f-row f-fredir">
|
||||
<div class="f-cell f-cmain">
|
||||
|
@ -160,7 +160,7 @@
|
|||
</div>
|
||||
</section>
|
||||
<div class="f-nav-links">
|
||||
@if($newTopic || $pages)
|
||||
@if($p->newTopic || $p->pages)
|
||||
<div class="f-links-a clearfix">
|
||||
@yield('linkpost')
|
||||
@yield('pages')
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@extends('layouts/main')
|
||||
@if($forums)
|
||||
@if($p->forums)
|
||||
<section class="f-main">
|
||||
<ol class="f-ftlist">
|
||||
@foreach($forums as $id => $cat)
|
||||
@foreach($p->forums as $id => $cat)
|
||||
<li id="cat-{!! $id !!}" class="f-category">
|
||||
<h2>{{ $cat['name'] }}</h2>
|
||||
<ol class="f-table">
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
@extends('layouts/main')
|
||||
<div class="f-main clearfix">
|
||||
<aside class="f-admin-menu">
|
||||
@if(!empty($aNavigation))
|
||||
@if($p->aNavigation)
|
||||
<nav class="admin-nav f-menu">
|
||||
<input id="admin-nav-checkbox" style="display: none;" type="checkbox">
|
||||
<label class="f-menu-toggle" for="admin-nav-checkbox"></label>
|
||||
@foreach($aNavigation as $aNameSub => $aNavigationSub)
|
||||
@foreach($p->aNavigation as $aNameSub => $aNavigationSub)
|
||||
<h2 class="f-menu-items">{!! __($aNameSub) !!}</h2>
|
||||
<ul class="f-menu-items">
|
||||
@foreach($aNavigationSub as $key => $val)
|
||||
@if($key == $aIndex)
|
||||
@if($key == $p->aIndex)
|
||||
<li><a id="anav-{{ $key }}" class="active" href="{!! $val[0] !!}">{!! $val[1] !!}</a></li>
|
||||
@else
|
||||
<li><a id="anav-{{ $key }}" href="{!! $val[0] !!}">{!! $val[1] !!}</a></li>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<section class="f-debug">
|
||||
<h2>{!! __('Debug table') !!}</h2>
|
||||
<p class="f-debugtime">[ {!! __('Querytime', $time, $numQueries) !!} - {!! __('Memory usage', $memory) !!} {!! __('Peak usage', $peak) !!} ]</p>
|
||||
@if($queries)
|
||||
<p class="f-debugtime">[ {!! __('Querytime', $p->time, $p->numQueries) !!} - {!! __('Memory usage', $p->memory) !!} {!! __('Peak usage', $p->peak) !!} ]</p>
|
||||
@if($p->queries)
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -10,14 +10,14 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($queries as $cur)
|
||||
@foreach($p->queries as $cur)
|
||||
<tr>
|
||||
<td class="tcl">{{ $cur[1] }}</td>
|
||||
<td class="tcr">{{ $cur[0] }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<tr>
|
||||
<td class="tcl">{{ $total }}</td>
|
||||
<td class="tcl">{{ $p->total }}</td>
|
||||
<td class="tcr"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
@if($cur['type'] === 'textarea')
|
||||
<textarea{!! empty($cur['required']) ? '' : ' required' !!} class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}">{{ $cur['value'] or '' }}</textarea>
|
||||
@if(isset($cur['bb']))
|
||||
<ul class="f-child5">
|
||||
<ul class="f-child5">
|
||||
@foreach($cur['bb'] as $val)
|
||||
<li><span><a href="{!! $val[0] !!}">{!! $val[1] !!}</a> {!! $val[2] !!}</span></li>
|
||||
<li><span><a href="{!! $val[0] !!}">{!! $val[1] !!}</a> {!! $val[2] !!}</span></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</ul>
|
||||
@endif
|
||||
@elseif($cur['type'] === 'text')
|
||||
<input{!! empty($cur['required']) ? '' : ' required' !!} class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}" type="text" maxlength="{{ $cur['maxlength'] or '' }}" pattern="{{ $cur['pattern'] or '' }}" value="{{ $cur['value'] or '' }}">
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{!! __('ForkBB Installation') !!}</title>
|
||||
@foreach($pageHeads as $cur)
|
||||
@foreach($p->pageHeads as $cur)
|
||||
<{!! $cur !!}>
|
||||
@endforeach
|
||||
</head>
|
||||
|
@ -16,18 +16,18 @@
|
|||
<p class="f-description">{!! __('Welcome') !!}</p>
|
||||
</div>
|
||||
</header>
|
||||
@if($fIswev)
|
||||
@if($p->fIswev)
|
||||
@include('layouts/iswev')
|
||||
@endif
|
||||
@if(is_array($installLangs))
|
||||
@if(is_array($p->installLangs))
|
||||
<section class="f-install">
|
||||
<div class="f-fdiv">
|
||||
<h2>{!! __('Choose install language') !!}</h2>
|
||||
<form class="f-form" method="post" action="{!! $formAction !!}">
|
||||
<form class="f-form" method="post" action="{!! $p->formAction !!}">
|
||||
<div>
|
||||
<label class="f-child1">{!! __('Install language') !!}</label>
|
||||
<select class="f-ctrl" id="id-installlang" name="installlang">
|
||||
@foreach($installLangs as $cur)
|
||||
@foreach($p->installLangs as $cur)
|
||||
@if(isset($cur[1]))
|
||||
<option value="{{ $cur[0] }}" selected>{{ $cur[0] }}</option>
|
||||
@else
|
||||
|
@ -44,12 +44,12 @@
|
|||
</div>
|
||||
</section>
|
||||
@endif
|
||||
@if(empty($fIswev['e']))
|
||||
@if(empty($p->fIswev['e']))
|
||||
<section class="f-main f-install">
|
||||
<div class="f-fdiv">
|
||||
<h2>{!! __('Install', $rev) !!}</h2>
|
||||
<form class="f-form" method="post" action="{!! $formAction !!}" autocomplete="off">
|
||||
<input type="hidden" name="installlang" value="{!! $installLang !!}">
|
||||
<h2>{!! __('Install', $p->rev) !!}</h2>
|
||||
<form class="f-form" method="post" action="{!! $p->formAction !!}" autocomplete="off">
|
||||
<input type="hidden" name="installlang" value="{!! $p->installLang !!}">
|
||||
<div class="f-finfo">
|
||||
<h3>{!! __('Database setup') !!}</h3>
|
||||
<p>{!! __('Info 1') !!}</p>
|
||||
|
@ -57,7 +57,7 @@
|
|||
<div>
|
||||
<label class="f-child1 f-req">{!! __('Database type') !!}</label>
|
||||
<select class="f-ctrl" id="id-dbtype" name="dbtype">
|
||||
@foreach($dbTypes as $key => $cur)
|
||||
@foreach($p->dbTypes as $key => $cur)
|
||||
@if(empty($cur[1]))
|
||||
<option value="{{ $key }}">{{ $cur[0] }}</option>
|
||||
@else
|
||||
|
@ -69,17 +69,17 @@
|
|||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-dbhost">{!! __('Database server hostname') !!}</label>
|
||||
<input required class="f-ctrl" id="id-dbhost" type="text" name="dbhost" value="{{ $dbhost }}">
|
||||
<input required class="f-ctrl" id="id-dbhost" type="text" name="dbhost" value="{{ $p->dbhost }}">
|
||||
<label class="f-child4">{!! __('Info 3') !!}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-dbname">{!! __('Database name') !!}</label>
|
||||
<input required class="f-ctrl" id="id-dbname" type="text" name="dbname" value="{{ $dbname }}">
|
||||
<input required class="f-ctrl" id="id-dbname" type="text" name="dbname" value="{{ $p->dbname }}">
|
||||
<label class="f-child4">{!! __('Info 4') !!}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="f-child1" for="id-dbuser">{!! __('Database username') !!}</label>
|
||||
<input class="f-ctrl" id="id-dbuser" type="text" name="dbuser" value="{{ $dbuser }}">
|
||||
<input class="f-ctrl" id="id-dbuser" type="text" name="dbuser" value="{{ $p->dbuser }}">
|
||||
</div>
|
||||
<div>
|
||||
<label class="f-child1" for="id-dbpass">{!! __('Database password') !!}</label>
|
||||
|
@ -88,7 +88,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<label class="f-child1" for="id-dbprefix">{!! __('Table prefix') !!}</label>
|
||||
<input class="f-ctrl" id="id-dbprefix" type="text" name="dbprefix" value="{{ $dbprefix }}" maxlength="40" pattern="^[a-zA-Z][a-zA-Z\d_]*$">
|
||||
<input class="f-ctrl" id="id-dbprefix" type="text" name="dbprefix" value="{{ $p->dbprefix }}" maxlength="40" pattern="^[a-zA-Z][a-zA-Z\d_]*$">
|
||||
<label class="f-child4">{!! __('Info 6') !!}</label>
|
||||
</div>
|
||||
<div class="f-finfo">
|
||||
|
@ -97,7 +97,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-username">{!! __('Administrator username') !!}</label>
|
||||
<input required class="f-ctrl" id="id-username" type="text" name="username" value="{{ $username }}" maxlength="25" pattern="^.{2,25}$">
|
||||
<input required class="f-ctrl" id="id-username" type="text" name="username" value="{{ $p->username }}" maxlength="25" pattern="^.{2,25}$">
|
||||
<label class="f-child4">{!! __('Info 8') !!}</label>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -107,7 +107,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-email">{!! __('Administrator email') !!}</label>
|
||||
<input required class="f-ctrl" id="id-email" type="text" name="email" value="{{ $email }}" maxlength="80" pattern=".+@.+">
|
||||
<input required class="f-ctrl" id="id-email" type="text" name="email" value="{{ $p->email }}" maxlength="80" pattern=".+@.+">
|
||||
<label class="f-child4">{!! __('Info 10') !!}</label>
|
||||
</div>
|
||||
<div class="f-finfo">
|
||||
|
@ -116,21 +116,21 @@
|
|||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-title">{!! __('Board title') !!}</label>
|
||||
<input required class="f-ctrl" id="id-title" type="text" name="title" value="{{ $title }}">
|
||||
<input required class="f-ctrl" id="id-title" type="text" name="title" value="{{ $p->title }}">
|
||||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-descr">{!! __('Board description') !!}</label>
|
||||
<input required class="f-ctrl" id="id-descr" type="text" name="descr" value="{{ $descr }}">
|
||||
<input required class="f-ctrl" id="id-descr" type="text" name="descr" value="{{ $p->descr }}">
|
||||
</div>
|
||||
<div>
|
||||
<label class="f-child1 f-req" for="id-baseurl">{!! __('Base URL') !!}</label>
|
||||
<input required class="f-ctrl" id="id-baseurl" type="text" name="baseurl" value="{{ $baseurl }}">
|
||||
<input required class="f-ctrl" id="id-baseurl" type="text" name="baseurl" value="{{ $p->baseurl }}">
|
||||
</div>
|
||||
@if(is_array($defaultLangs))
|
||||
@if(is_array($p->defaultLangs))
|
||||
<div>
|
||||
<label class="f-child1 f-req">{!! __('Default language') !!}</label>
|
||||
<select class="f-ctrl" id="id-defaultlang" name="defaultlang">
|
||||
@foreach($defaultLangs as $cur)
|
||||
@foreach($p->defaultLangs as $cur)
|
||||
@if(isset($cur[1]))
|
||||
<option value="{{ $cur[0] }}" selected>{{ $cur[0] }}</option>
|
||||
@else
|
||||
|
@ -140,12 +140,12 @@
|
|||
</select>
|
||||
</div>
|
||||
@else
|
||||
<input type="hidden" name="defaultlang" value="{!! $defaultLangs !!}">
|
||||
<input type="hidden" name="defaultlang" value="{!! $p->defaultLangs !!}">
|
||||
@endif
|
||||
<div>
|
||||
<label class="f-child1 f-req">{!! __('Default style') !!}</label>
|
||||
<select class="f-ctrl" id="id-defaultstyle" name="defaultstyle">
|
||||
@foreach($defaultStyles as $cur)
|
||||
@foreach($p->defaultStyles as $cur)
|
||||
@if(isset($cur[1]))
|
||||
<option value="{{ $cur[0] }}" selected>{{ $cur[0] }}</option>
|
||||
@else
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
@if(isset($fIswev['i']))
|
||||
@if(isset($p->fIswev['i']))
|
||||
<section class="f-iswev f-info">
|
||||
<h2>Info message</h2>
|
||||
<ul>
|
||||
@foreach($fIswev['i'] as $cur)
|
||||
@foreach($p->fIswev['i'] as $cur)
|
||||
<li class="f-icontent">{!! $cur !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</section>
|
||||
@endif
|
||||
@if(isset($fIswev['s']))
|
||||
@if(isset($p->fIswev['s']))
|
||||
<section class="f-iswev f-success">
|
||||
<h2>Successful operation message</h2>
|
||||
<ul>
|
||||
@foreach($fIswev['s'] as $cur)
|
||||
@foreach($p->fIswev['s'] as $cur)
|
||||
<li class="f-scontent">{!! $cur !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</section>
|
||||
@endif
|
||||
@if(isset($fIswev['w']))
|
||||
@if(isset($p->fIswev['w']))
|
||||
<section class="f-iswev f-warning">
|
||||
<h2>Warning message</h2>
|
||||
<ul>
|
||||
@foreach($fIswev['w'] as $cur)
|
||||
@foreach($p->fIswev['w'] as $cur)
|
||||
<li class="f-wcontent">{!! $cur !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</section>
|
||||
@endif
|
||||
@if(isset($fIswev['e']))
|
||||
@if(isset($p->fIswev['e']))
|
||||
<section class="f-iswev f-error">
|
||||
<h2>Error message</h2>
|
||||
<ul>
|
||||
@foreach($fIswev['e'] as $cur)
|
||||
@foreach($p->fIswev['e'] as $cur)
|
||||
<li class="f-econtent">{!! $cur !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</section>
|
||||
@endif
|
||||
@if(isset($fIswev['v']))
|
||||
@if(isset($p->fIswev['v']))
|
||||
<section class="f-iswev f-validation">
|
||||
<h2>Validation message</h2>
|
||||
<ul>
|
||||
@foreach($fIswev['v'] as $cur)
|
||||
@foreach($p->fIswev['v'] as $cur)
|
||||
<li class="f-vcontent">{!! $cur !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ $pageTitle }}</title>
|
||||
@foreach($pageHeaders as $cur)
|
||||
<title>{{ $p->pageTitle }}</title>
|
||||
@foreach($p->pageHeaders as $cur)
|
||||
<{!! $cur !!}>
|
||||
@endforeach
|
||||
</head>
|
||||
|
@ -12,16 +12,16 @@
|
|||
<div class="f-wrap">
|
||||
<header class="f-header">
|
||||
<div class="f-title">
|
||||
<h1><a href="{!! $fRootLink !!}">{{ $fTitle }}</a></h1>
|
||||
<p class="f-description">{!! $fDescription !!}</p>
|
||||
<h1><a href="{!! $p->fRootLink !!}">{{ $p->fTitle }}</a></h1>
|
||||
<p class="f-description">{!! $p->fDescription !!}</p>
|
||||
</div>
|
||||
@if(!empty($fNavigation))
|
||||
@if($p->fNavigation)
|
||||
<nav class="main-nav f-menu">
|
||||
<input id="main-nav-checkbox" style="display: none;" type="checkbox">
|
||||
<label class="f-menu-toggle" for="main-nav-checkbox"></label>
|
||||
<ul class="f-menu-items">
|
||||
@foreach($fNavigation as $key => $val)
|
||||
@if($key == $fIndex)
|
||||
@foreach($p->fNavigation as $key => $val)
|
||||
@if($key == $p->fIndex)
|
||||
<li><a id="nav-{{ $key }}" class="active" href="{!! $val[0] !!}">{!! $val[1] !!}</a></li>
|
||||
@else
|
||||
<li><a id="nav-{{ $key }}" href="{!! $val[0] !!}">{!! $val[1] !!}</a></li>
|
||||
|
@ -31,13 +31,13 @@
|
|||
</nav>
|
||||
@endif
|
||||
</header>
|
||||
@if($fAnnounce)
|
||||
@if($p->fAnnounce)
|
||||
<section class="f-announce">
|
||||
<h2>{!! __('Announcement') !!}</h2>
|
||||
<p class="f-ancontent">{!! $fAnnounce !!}</p>
|
||||
<p class="f-ancontent">{!! $p->fAnnounce !!}</p>
|
||||
</section>
|
||||
@endif
|
||||
@if($fIswev)
|
||||
@if($p->fIswev)
|
||||
@include('layouts/iswev')
|
||||
@endif
|
||||
@yield('content')
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="refresh" content="{!! $timeout !!};URL={{ $link }}">
|
||||
<title>{{ $pageTitle }}</title>
|
||||
@foreach($pageHeaders as $cur)
|
||||
<meta http-equiv="refresh" content="{!! $p->timeout !!};URL={{ $p->link }}">
|
||||
<title>{{ $p->pageTitle }}</title>
|
||||
@foreach($p->pageHeaders as $cur)
|
||||
<{!! $cur !!}>
|
||||
@endforeach
|
||||
</head>
|
||||
|
@ -13,8 +13,8 @@
|
|||
<div class="f-wrap">
|
||||
<section class="f-main f-redirect">
|
||||
<h2>{!! __('Redirecting') !!}</h2>
|
||||
<p>{!! $message !!}</p>
|
||||
<p><a href="{{ $link }}">{!! __('Click redirect') !!}</a></p>
|
||||
<p>{!! $p->message !!}</p>
|
||||
<p><a href="{{ $p->link }}">{!! __('Click redirect') !!}</a></p>
|
||||
</section>
|
||||
<!-- debuginfo -->
|
||||
</div>
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
<section class="f-stats">
|
||||
<h2>{!! __('Stats info') !!}</h2>
|
||||
<div class="clearfix">
|
||||
@if($stats)
|
||||
@if($p->stats)
|
||||
<dl class="right">
|
||||
<dt>{!! __('Board stats') !!}</dt>
|
||||
<dd>{!! __('No of users') !!} <strong>{!! $stats['total_users'] !!}</strong></dd>
|
||||
<dd>{!! __('No of topics') !!} <strong>{!! $stats['total_topics'] !!}</strong></dd>
|
||||
<dd>{!! __('No of posts') !!} <strong>{!! $stats['total_posts'] !!}</strong></dd>
|
||||
<dd>{!! __('No of users') !!} <strong>{!! $p->stats['total_users'] !!}</strong></dd>
|
||||
<dd>{!! __('No of topics') !!} <strong>{!! $p->stats['total_topics'] !!}</strong></dd>
|
||||
<dd>{!! __('No of posts') !!} <strong>{!! $p->stats['total_posts'] !!}</strong></dd>
|
||||
</dl>
|
||||
@endif
|
||||
<dl class="left">
|
||||
<dt>{!! __('User info') !!}</dt>
|
||||
@if($stats && is_string($stats['newest_user']))
|
||||
<dd>{!! __('Newest user') !!} {{ $stats['newest_user'] }}</dd>
|
||||
@elseif($stats)
|
||||
<dd>{!! __('Newest user') !!} <a href="{!! $stats['newest_user'][0] !!}">{{ $stats['newest_user'][1] }}</a></dd>
|
||||
@if($p->stats && is_string($p->stats['newest_user']))
|
||||
<dd>{!! __('Newest user') !!} {{ $p->stats['newest_user'] }}</dd>
|
||||
@elseif($p->stats)
|
||||
<dd>{!! __('Newest user') !!} <a href="{!! $p->stats['newest_user'][0] !!}">{{ $p->stats['newest_user'][1] }}</a></dd>
|
||||
@endif
|
||||
@if($online)
|
||||
<dd>{!! __('Visitors online', $online['number_of_users'], $online['number_of_guests']) !!}</dd>
|
||||
@if($p->online)
|
||||
<dd>{!! __('Visitors online', $p->online['number_of_users'], $p->online['number_of_guests']) !!}</dd>
|
||||
@endif
|
||||
@if($stats)
|
||||
<dd>{!! __('Most online', $online['max'], $online['max_time']) !!}</dd>
|
||||
@if($p->stats)
|
||||
<dd>{!! __('Most online', $p->online['max'], $p->online['max_time']) !!}</dd>
|
||||
@endif
|
||||
</dl>
|
||||
@if($online && $online['list'])
|
||||
@if($p->online && $p->online['list'])
|
||||
<dl class="f-inline f-onlinelist"><!-- inline -->
|
||||
<dt>{!! __('Online users') !!}</dt>
|
||||
@foreach($online['list'] as $cur)
|
||||
@foreach($p->online['list'] as $cur)
|
||||
@if(is_string($cur))
|
||||
<dd>{{ $cur }}</dd>
|
||||
@else
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
<section class="f-main f-login">
|
||||
<div class="f-fdiv f-lrdiv">
|
||||
<h2>{!! __('Login') !!}</h2>
|
||||
<form class="f-form" method="post" action="{!! $formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $formToken !!}">
|
||||
<input type="hidden" name="redirect" value="{{ $redirect }}">
|
||||
<form class="f-form" method="post" action="{!! $p->formAction !!}">
|
||||
<input type="hidden" name="token" value="{!! $p->formToken !!}">
|
||||
<input type="hidden" name="redirect" value="{{ $p->redirect }}">
|
||||
<fieldset>
|
||||
<dl>
|
||||
<dt><label class="f-child1 f-req" for="id-username">{!! __('Username') !!}</label></dt>
|
||||
<dd>
|
||||
<input required class="f-ctrl" id="id-username" type="text" name="username" value="{{ $username }}" maxlength="25" autofocus spellcheck="false" tabindex="1">
|
||||
<input required class="f-ctrl" id="id-username" type="text" name="username" value="{{ $p->username }}" maxlength="25" autofocus spellcheck="false" tabindex="1">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><label class="f-child1 f-req" for="id-password">{!! __('Passphrase') !!}<a class="f-forgetlink" href="{!! $forgetLink !!}" tabindex="5">{!! __('Forgotten pass') !!}</a></label></dt>
|
||||
<dt><label class="f-child1 f-req" for="id-password">{!! __('Passphrase') !!}<a class="f-forgetlink" href="{!! $p->forgetLink !!}" tabindex="5">{!! __('Forgotten pass') !!}</a></label></dt>
|
||||
<dd>
|
||||
<input required class="f-ctrl" id="id-password" type="password" name="password" tabindex="2">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt></dt>
|
||||
@if($save)
|
||||
@if($p->save)
|
||||
<dd><label class="f-child2"><input type="checkbox" name="save" value="1" tabindex="3" checked>{!! __('Remember me') !!}</label></dd>
|
||||
@else
|
||||
<dd><label class="f-child2"><input type="checkbox" name="save" value="1" tabindex="3">{!! __('Remember me') !!}</label></dd>
|
||||
|
@ -32,9 +32,9 @@
|
|||
</p>
|
||||
</form>
|
||||
</div>
|
||||
@if($regLink)
|
||||
@if($p->regLink)
|
||||
<div class="f-fdiv f-lrdiv">
|
||||
<p class="f-child3"><a href="{!! $regLink !!}" tabindex="6">{!! __('Not registered') !!}</a></p>
|
||||
<p class="f-child3"><a href="{!! $p->regLink !!}" tabindex="6">{!! __('Not registered') !!}</a></p>
|
||||
</div>
|
||||
@endif
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@extends('layouts/main')
|
||||
<section class="f-main f-maintenance">
|
||||
<h2>{{ __('Maintenance') }}</h2>
|
||||
<p>{!! $maintenanceMessage !!}</p>
|
||||
<p>{!! $p->maintenanceMessage !!}</p>
|
||||
</section>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@extends('layouts/main')
|
||||
<section class="f-main f-message">
|
||||
<h2>{!! __('Info') !!}</h2>
|
||||
<p>{!! $message !!}</p>
|
||||
@if($back)
|
||||
<p>{!! $p->message !!}</p>
|
||||
@if($p->back)
|
||||
<p><a href="javascript: history.go(-1)">{!! __('Go back') !!}</a></p>
|
||||
@endif
|
||||
</section>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue