From 37f80f6fb8abbb8567526479991c5311ea9a3522 Mon Sep 17 00:00:00 2001 From: Visman Date: Fri, 3 Nov 2017 20:06:22 +0700 Subject: [PATCH] 2017-11-03 --- app/Controllers/Install.php | 6 +- app/Controllers/Primary.php | 22 +- app/Controllers/Routing.php | 18 +- app/Core/AbstractModel.php | 120 ----- app/Core/Cache/FileCache.php | 13 +- app/Core/Container.php | 26 +- app/Core/Cookie.php | 118 ----- app/Core/Csrf.php | 5 + app/Core/DB.php | 24 +- app/Core/DB/mysql.php | 41 ++ app/Core/Func.php | 11 +- app/Core/Lang.php | 12 +- app/Core/Mail.php | 42 ++ app/Core/Request.php | 244 --------- app/Core/Router.php | 10 + app/Core/Secury.php | 24 +- app/Core/Validator.php | 40 +- app/Core/View.php | 41 +- app/Models/Actions/CacheGenerator.php | 12 +- app/Models/Actions/CacheLoader.php | 2 +- app/Models/Actions/CheckBans.php | 111 ----- app/Models/AdminList.php | 23 + app/Models/AdminList/Load.php | 22 + app/Models/BanList.php | 46 ++ app/Models/BanList/Check.php | 67 +++ app/Models/BanList/Delete.php | 25 + app/Models/BanList/IsBanned.php | 35 ++ app/Models/BanList/Load.php | 60 +++ app/Models/CensorshipList.php | 41 ++ app/Models/CensorshipList/Load.php | 33 ++ app/Models/Config.php | 23 + app/Models/Config/Load.php | 22 + app/Models/Config/Save.php | 37 ++ app/Models/Cookie.php | 212 ++++++++ app/Models/DBMap.php | 25 + app/Models/DataModel.php | 91 ++++ app/Models/Forum.php | 54 ++ app/Models/ForumList.php | 62 +++ app/Models/ForumList/Load.php | 93 ++++ app/Models/ForumList/LoadTree.php | 132 +++++ app/Models/MethodModel.php | 33 ++ app/Models/Model.php | 115 +++++ app/Models/Online.php | 70 ++- app/Models/{Pages => }/Page.php | 471 +++++++----------- app/Models/Pages/Admin.php | 90 ++++ app/Models/Pages/Admin/Admin.php | 105 ---- app/Models/Pages/Admin/Groups.php | 74 ++- app/Models/Pages/Admin/Index.php | 26 +- app/Models/Pages/Admin/Statistics.php | 54 +- app/Models/Pages/Auth.php | 201 ++++---- app/Models/Pages/Ban.php | 55 +- app/Models/Pages/CrumbTrait.php | 31 +- app/Models/Pages/Debug.php | 49 +- app/Models/Pages/Forum.php | 102 ++-- app/Models/Pages/ForumsTrait.php | 142 ++---- app/Models/Pages/Index.php | 63 +-- app/Models/Pages/Install.php | 191 +++---- app/Models/Pages/Maintenance.php | 61 +-- app/Models/Pages/OnlineTrait.php | 21 +- app/Models/Pages/Post.php | 68 +++ app/Models/Pages/Redirect.php | 78 +-- app/Models/Pages/Register.php | 177 ++++--- app/Models/Pages/Rules.php | 61 +-- app/Models/Pages/Topic.php | 417 +++++++++------- app/Models/Pages/UsersTrait.php | 16 +- app/Models/SmileyList.php | 23 + app/Models/SmileyList/Load.php | 22 + app/Models/Stats.php | 30 ++ app/Models/Stats/Load.php | 27 + app/Models/Stopwords.php | 82 +++ app/Models/User.php | 60 +-- app/Models/User/IsUnique.php | 26 + app/Models/User/Load.php | 46 ++ .../{Actions => User}/LoadUserFromCookie.php | 121 +++-- app/Models/User/Save.php | 71 +++ app/Models/User/UpdateLastVisit.php | 19 + app/Models/UserCookie.php | 157 ------ app/Models/UserMapper.php | 177 ------- app/bootstrap.php | 13 +- app/lang/English/common.po | 4 +- app/lang/Russian/common.po | 6 +- app/templates/admin/group.tpl | 22 +- app/templates/admin/groups.tpl | 30 +- app/templates/admin/index.tpl | 4 +- app/templates/admin/statistics.tpl | 20 +- app/templates/ban.tpl | 10 +- app/templates/change_passphrase.tpl | 4 +- app/templates/forum.tpl | 22 +- app/templates/index.tpl | 4 +- app/templates/layouts/admin.tpl | 6 +- app/templates/layouts/debug.tpl | 8 +- app/templates/layouts/form.tpl | 6 +- app/templates/layouts/install.tpl | 46 +- app/templates/layouts/iswev.tpl | 20 +- app/templates/layouts/main.tpl | 20 +- app/templates/layouts/redirect.tpl | 10 +- app/templates/layouts/stats.tpl | 28 +- app/templates/login.tpl | 16 +- app/templates/maintenance.tpl | 2 +- app/templates/message.tpl | 4 +- app/templates/passphrase_reset.tpl | 6 +- app/templates/register.tpl | 12 +- app/templates/rules.tpl | 12 +- app/templates/topic.tpl | 28 +- 104 files changed, 3370 insertions(+), 2670 deletions(-) delete mode 100644 app/Core/AbstractModel.php delete mode 100644 app/Core/Cookie.php delete mode 100644 app/Core/Request.php delete mode 100644 app/Models/Actions/CheckBans.php create mode 100644 app/Models/AdminList.php create mode 100644 app/Models/AdminList/Load.php create mode 100644 app/Models/BanList.php create mode 100644 app/Models/BanList/Check.php create mode 100644 app/Models/BanList/Delete.php create mode 100644 app/Models/BanList/IsBanned.php create mode 100644 app/Models/BanList/Load.php create mode 100644 app/Models/CensorshipList.php create mode 100644 app/Models/CensorshipList/Load.php create mode 100644 app/Models/Config.php create mode 100644 app/Models/Config/Load.php create mode 100644 app/Models/Config/Save.php create mode 100644 app/Models/Cookie.php create mode 100644 app/Models/DBMap.php create mode 100644 app/Models/DataModel.php create mode 100644 app/Models/Forum.php create mode 100644 app/Models/ForumList.php create mode 100644 app/Models/ForumList/Load.php create mode 100644 app/Models/ForumList/LoadTree.php create mode 100644 app/Models/MethodModel.php create mode 100644 app/Models/Model.php rename app/Models/{Pages => }/Page.php (50%) create mode 100644 app/Models/Pages/Admin.php delete mode 100644 app/Models/Pages/Admin/Admin.php create mode 100644 app/Models/Pages/Post.php create mode 100644 app/Models/SmileyList.php create mode 100644 app/Models/SmileyList/Load.php create mode 100644 app/Models/Stats.php create mode 100644 app/Models/Stats/Load.php create mode 100644 app/Models/Stopwords.php create mode 100644 app/Models/User/IsUnique.php create mode 100644 app/Models/User/Load.php rename app/Models/{Actions => User}/LoadUserFromCookie.php (61%) create mode 100644 app/Models/User/Save.php create mode 100644 app/Models/User/UpdateLastVisit.php delete mode 100644 app/Models/UserCookie.php delete mode 100644 app/Models/UserMapper.php diff --git a/app/Controllers/Install.php b/app/Controllers/Install.php index d4a59299..32391255 100644 --- a/app/Controllers/Install.php +++ b/app/Controllers/Install.php @@ -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; diff --git a/app/Controllers/Primary.php b/app/Controllers/Primary.php index d1dcfb6c..0b30beb1 100644 --- a/app/Controllers/Primary.php +++ b/app/Controllers/Primary.php @@ -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); } } } diff --git a/app/Controllers/Routing.php b/app/Controllers/Routing.php index 839c5e6a..c3fc55e5 100644 --- a/app/Controllers/Routing.php +++ b/app/Controllers/Routing.php @@ -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'); // юзеры @@ -93,7 +95,7 @@ class Routing $r->add('GET', '/post/{id:[1-9]\d*}/delete', 'Delete:delete', 'DeletePost'); //???? $r->add('GET', '/post/{id:[1-9]\d*}/edit', 'Edit:edit', 'EditPost'); //???? $r->add('GET', '/post/{id:[1-9]\d*}/report', 'Report:report', 'ReportPost'); //???? - + } // админ и модератор if ($user->isAdmMod) { @@ -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'); } diff --git a/app/Core/AbstractModel.php b/app/Core/AbstractModel.php deleted file mode 100644 index e9a57ce0..00000000 --- a/app/Core/AbstractModel.php +++ /dev/null @@ -1,120 +0,0 @@ -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); - } -} diff --git a/app/Core/Cache/FileCache.php b/app/Core/Cache/FileCache.php index 7763d005..71bc7993 100644 --- a/app/Core/Cache/FileCache.php +++ b/app/Core/Cache/FileCache.php @@ -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) diff --git a/app/Core/Container.php b/app/Core/Container.php index 01270386..6f88dbec 100644 --- a/app/Core/Container.php +++ b/app/Core/Container.php @@ -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; } @@ -181,7 +191,7 @@ class Container '~%([a-z0-9_]+(?:\.[a-z0-9_]+)*)%~i', function ($matches) { return $this->__get($matches[1]); - }, + }, $value ); } diff --git a/app/Core/Cookie.php b/app/Core/Cookie.php deleted file mode 100644 index 0689d371..00000000 --- a/app/Core/Cookie.php +++ /dev/null @@ -1,118 +0,0 @@ -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; - } -} diff --git a/app/Core/Csrf.php b/app/Core/Csrf.php index f0074950..8624ada1 100644 --- a/app/Core/Csrf.php +++ b/app/Core/Csrf.php @@ -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 = []) diff --git a/app/Core/DB.php b/app/Core/DB.php index 1d281d5f..a35ecb3d 100644 --- a/app/Core/DB.php +++ b/app/Core/DB.php @@ -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 { @@ -127,7 +127,7 @@ class DB extends PDO $idxOut = 1; $map = []; $query = preg_replace_callback( - '%(?=[?:])(?dbPrefix . $matches[1]; @@ -170,7 +170,7 @@ class DB extends PDO $map[$key][] = $name; } return implode(',', $res); - }, + }, $query ); return $map; @@ -178,10 +178,10 @@ class DB extends PDO /** * Метод возвращает значение из массива параметров по ключу или исключение - * + * * @param mixed $key * @param array $params - * + * * @throws PDOException * * @return mixed @@ -189,7 +189,7 @@ class DB extends PDO public function getValue($key, array $params) { if ( - is_string($key) + is_string($key) && (isset($params[':' . $key]) || array_key_exists(':' . $key, $params)) ) { return $params[':' . $key]; @@ -205,7 +205,7 @@ class DB extends PDO /** * Метод для получения количества выполненных запросов - * + * * @return int */ public function getCount() @@ -215,7 +215,7 @@ class DB extends PDO /** * Метод для получения статистики выполненных запросов - * + * * @return array */ public function getQueries() @@ -225,7 +225,7 @@ class DB extends PDO /** * Метод для сохранения статистики по выполненному запросу - * + * * @param string $query * @param float $time */ @@ -291,11 +291,11 @@ class DB extends PDO } $map = $this->parse($query, $params); - + $start = microtime(true); $stmt = parent::prepare($query, $options); $this->delta = microtime(true) - $start; - + $stmt->setMap($map); $stmt->bindValueList($params); @@ -331,7 +331,7 @@ class DB extends PDO $start = microtime(true); $stmt = parent::prepare($query); $this->delta = microtime(true) - $start; - + $stmt->setMap($map); if ($stmt->execute($params)) { diff --git a/app/Core/DB/mysql.php b/app/Core/DB/mysql.php index 772fafb0..ef8d12cf 100644 --- a/app/Core/DB/mysql.php +++ b/app/Core/DB/mysql.php @@ -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; + } } diff --git a/app/Core/Func.php b/app/Core/Func.php index b391869d..b45063f9 100644 --- a/app/Core/Func.php +++ b/app/Core/Func.php @@ -24,6 +24,8 @@ class Func /** * Конструктор + * + * @param Container $container */ public function __construct(Container $container) { @@ -61,13 +63,16 @@ class Func } /** + * Пагинация + * * @param int $all * @param int $cur * @param string $marker * @param array $args - * @return array + * + * @return array */ - public function paginate($all, $cur, $marker, array $args = []) + public function paginate($all, $cur, $marker, array $args = []) { $pages = []; if ($all < 2) { @@ -88,7 +93,7 @@ class Func } $tpl[$all] = $all; } else { - $tpl = $all < 7 + $tpl = $all < 7 ? array_slice([2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6], 0, $all - 1) : [2 => 2, 3 => 3, 4 => 4, $all => $all]; } diff --git a/app/Core/Lang.php b/app/Core/Lang.php index 04c5378b..31407922 100644 --- a/app/Core/Lang.php +++ b/app/Core/Lang.php @@ -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 ); } - } diff --git a/app/Core/Mail.php b/app/Core/Mail.php index c4625cda..62643620 100644 --- a/app/Core/Mail.php +++ b/app/Core/Mail.php @@ -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() diff --git a/app/Core/Request.php b/app/Core/Request.php deleted file mode 100644 index eca6625d..00000000 --- a/app/Core/Request.php +++ /dev/null @@ -1,244 +0,0 @@ -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; - } -} diff --git a/app/Core/Router.php b/app/Core/Router.php index eeb4e771..30c7ff3f 100644 --- a/app/Core/Router.php +++ b/app/Core/Router.php @@ -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) diff --git a/app/Core/Secury.php b/app/Core/Secury.php index ccd46db8..3200fb20 100644 --- a/app/Core/Secury.php +++ b/app/Core/Secury.php @@ -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) diff --git a/app/Core/Validator.php b/app/Core/Validator.php index 6b91399b..68c602ed 100644 --- a/app/Core/Validator.php +++ b/app/Core/Validator.php @@ -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() diff --git a/app/Core/View.php b/app/Core/View.php index d7173bd8..72e1907e 100644 --- a/app/Core/View.php +++ b/app/Core/View.php @@ -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'); } } diff --git a/app/Models/Actions/CacheGenerator.php b/app/Models/Actions/CacheGenerator.php index 9ad94df7..65682cc5 100644 --- a/app/Models/Actions/CacheGenerator.php +++ b/app/Models/Actions/CacheGenerator.php @@ -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; } diff --git a/app/Models/Actions/CacheLoader.php b/app/Models/Actions/CacheLoader.php index dde942f4..59781969 100644 --- a/app/Models/Actions/CacheLoader.php +++ b/app/Models/Actions/CacheLoader.php @@ -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()); diff --git a/app/Models/Actions/CheckBans.php b/app/Models/Actions/CheckBans.php deleted file mode 100644 index 4bed1652..00000000 --- a/app/Models/Actions/CheckBans.php +++ /dev/null @@ -1,111 +0,0 @@ -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; - } -} diff --git a/app/Models/AdminList.php b/app/Models/AdminList.php new file mode 100644 index 00000000..60e4a652 --- /dev/null +++ b/app/Models/AdminList.php @@ -0,0 +1,23 @@ +c->Cache->has('admins')) { + $this->list = $this->c->Cache->get('admins'); + } else { + $this->load(); + } + return $this; + } +} diff --git a/app/Models/AdminList/Load.php b/app/Models/AdminList/Load.php new file mode 100644 index 00000000..82230ee5 --- /dev/null +++ b/app/Models/AdminList/Load.php @@ -0,0 +1,22 @@ +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; + } +} diff --git a/app/Models/BanList.php b/app/Models/BanList.php new file mode 100644 index 00000000..bee2370f --- /dev/null +++ b/app/Models/BanList.php @@ -0,0 +1,46 @@ +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; + } + } +} diff --git a/app/Models/BanList/Check.php b/app/Models/BanList/Check.php new file mode 100644 index 00000000..c40e5690 --- /dev/null +++ b/app/Models/BanList/Check.php @@ -0,0 +1,67 @@ +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; + } +} diff --git a/app/Models/BanList/Delete.php b/app/Models/BanList/Delete.php new file mode 100644 index 00000000..237c430a --- /dev/null +++ b/app/Models/BanList/Delete.php @@ -0,0 +1,25 @@ +c->DB->exec('DELETE FROM ::bans WHERE id IN (?ai:ids)', [':ids' => $ids]); + $this->model->load(); + } + return $this->model; + } +} diff --git a/app/Models/BanList/IsBanned.php b/app/Models/BanList/IsBanned.php new file mode 100644 index 00000000..50a36921 --- /dev/null +++ b/app/Models/BanList/IsBanned.php @@ -0,0 +1,35 @@ +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; + } +} diff --git a/app/Models/BanList/Load.php b/app/Models/BanList/Load.php new file mode 100644 index 00000000..e390f779 --- /dev/null +++ b/app/Models/BanList/Load.php @@ -0,0 +1,60 @@ +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; + } +} diff --git a/app/Models/CensorshipList.php b/app/Models/CensorshipList.php new file mode 100644 index 00000000..98c23a2f --- /dev/null +++ b/app/Models/CensorshipList.php @@ -0,0 +1,41 @@ +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; + } + } +} diff --git a/app/Models/CensorshipList/Load.php b/app/Models/CensorshipList/Load.php new file mode 100644 index 00000000..41d549fd --- /dev/null +++ b/app/Models/CensorshipList/Load.php @@ -0,0 +1,33 @@ +c->DB->query('SELECT search_for, replace_with FROM ::censoring'); + $search = []; + $replace = []; + while ($row = $stmt->fetch()) { + $replace[] = $row['replace_with']; + $search[] = '%(?model->searchList = $search; + $this->model->replaceList = $replace; + $this->c->Cache->set('censorship', [ + 'searchList' => $search, + 'replaceList' => $replace, + ]); + return $this->model; + } +} diff --git a/app/Models/Config.php b/app/Models/Config.php new file mode 100644 index 00000000..9056270c --- /dev/null +++ b/app/Models/Config.php @@ -0,0 +1,23 @@ +c->Cache->has('config')) { + $this->setAttrs($this->c->Cache->get('config')); + } else { + $this->load(); + } + return $this; + } +} diff --git a/app/Models/Config/Load.php b/app/Models/Config/Load.php new file mode 100644 index 00000000..c4c1ed44 --- /dev/null +++ b/app/Models/Config/Load.php @@ -0,0 +1,22 @@ +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; + } +} diff --git a/app/Models/Config/Save.php b/app/Models/Config/Save.php new file mode 100644 index 00000000..819654bd --- /dev/null +++ b/app/Models/Config/Save.php @@ -0,0 +1,37 @@ +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; + } +} diff --git a/app/Models/Cookie.php b/app/Models/Cookie.php new file mode 100644 index 00000000..21628f10 --- /dev/null +++ b/app/Models/Cookie.php @@ -0,0 +1,212 @@ +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); + } +} diff --git a/app/Models/DBMap.php b/app/Models/DBMap.php new file mode 100644 index 00000000..8cd0a2c5 --- /dev/null +++ b/app/Models/DBMap.php @@ -0,0 +1,25 @@ +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; + } +} diff --git a/app/Models/DataModel.php b/app/Models/DataModel.php new file mode 100644 index 00000000..07e46862 --- /dev/null +++ b/app/Models/DataModel.php @@ -0,0 +1,91 @@ +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; + } + } +} diff --git a/app/Models/Forum.php b/app/Models/Forum.php new file mode 100644 index 00000000..f257b3bb --- /dev/null +++ b/app/Models/Forum.php @@ -0,0 +1,54 @@ + $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); + } +} diff --git a/app/Models/ForumList.php b/app/Models/ForumList.php new file mode 100644 index 00000000..b2e72522 --- /dev/null +++ b/app/Models/ForumList.php @@ -0,0 +1,62 @@ +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; + } + } +} diff --git a/app/Models/ForumList/Load.php b/app/Models/ForumList/Load.php new file mode 100644 index 00000000..1dbba436 --- /dev/null +++ b/app/Models/ForumList/Load.php @@ -0,0 +1,93 @@ +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; + } +} diff --git a/app/Models/ForumList/LoadTree.php b/app/Models/ForumList/LoadTree.php new file mode 100644 index 00000000..a1b58cb9 --- /dev/null +++ b/app/Models/ForumList/LoadTree.php @@ -0,0 +1,132 @@ +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; //???? + } + } + } +} diff --git a/app/Models/MethodModel.php b/app/Models/MethodModel.php new file mode 100644 index 00000000..2e1d814a --- /dev/null +++ b/app/Models/MethodModel.php @@ -0,0 +1,33 @@ +model = $model; + $this->c = $container; + } +} diff --git a/app/Models/Model.php b/app/Models/Model.php new file mode 100644 index 00000000..71f5718e --- /dev/null +++ b/app/Models/Model.php @@ -0,0 +1,115 @@ +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); + } + } +} diff --git a/app/Models/Online.php b/app/Models/Online.php index 85a1c060..c31b17bd 100644 --- a/app/Models/Online.php +++ b/app/Models/Online.php @@ -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) diff --git a/app/Models/Pages/Page.php b/app/Models/Page.php similarity index 50% rename from app/Models/Pages/Page.php rename to app/Models/Page.php index b2cd9443..27904233 100644 --- a/app/Models/Pages/Page.php +++ b/app/Models/Page.php @@ -1,118 +1,181 @@ 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')]; //''; + } + // 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')]; //''; - } - // 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."); - } } diff --git a/app/Models/Pages/Admin.php b/app/Models/Pages/Admin.php new file mode 100644 index 00000000..aebd1c32 --- /dev/null +++ b/app/Models/Pages/Admin.php @@ -0,0 +1,90 @@ +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); + } +} diff --git a/app/Models/Pages/Admin/Admin.php b/app/Models/Pages/Admin/Admin.php deleted file mode 100644 index 801d951f..00000000 --- a/app/Models/Pages/Admin/Admin.php +++ /dev/null @@ -1,105 +0,0 @@ -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; - } - -} diff --git a/app/Models/Pages/Admin/Groups.php b/app/Models/Pages/Admin/Groups.php index 00f8a6b7..4a9aeedc 100644 --- a/app/Models/Pages/Admin/Groups.php +++ b/app/Models/Pages/Admin/Groups.php @@ -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, diff --git a/app/Models/Pages/Admin/Index.php b/app/Models/Pages/Admin/Index.php index 34e764c5..f3f7ccb3 100644 --- a/app/Models/Pages/Admin/Index.php +++ b/app/Models/Pages/Admin/Index.php @@ -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; } } diff --git a/app/Models/Pages/Admin/Statistics.php b/app/Models/Pages/Admin/Statistics.php index 53f00139..44670f75 100644 --- a/app/Models/Pages/Admin/Statistics.php +++ b/app/Models/Pages/Admin/Statistics.php @@ -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'] = '' . __('Turck MMCache') . ''; + $this->accelerator = '' . __('Turck MMCache') . ''; } elseif (isset($_PHPA)) { - $this->data['accelerator'] = '' . __('ionCube PHP Accelerator') . ''; + $this->accelerator = '' . __('ionCube PHP Accelerator') . ''; } elseif (ini_get('apc.enabled')) { - $this->data['accelerator'] ='' . __('Alternative PHP Cache (APC)') . ''; + $this->accelerator ='' . __('Alternative PHP Cache (APC)') . ''; } elseif (ini_get('zend_optimizer.optimization_level')) { - $this->data['accelerator'] = '' . __('Zend Optimizer') . ''; + $this->accelerator = '' . __('Zend Optimizer') . ''; } elseif (ini_get('eaccelerator.enable')) { - $this->data['accelerator'] = '' . __('eAccelerator') . ''; + $this->accelerator = '' . __('eAccelerator') . ''; } elseif (ini_get('xcache.cacher')) { - $this->data['accelerator'] = '' . __('XCache') . ''; + $this->accelerator = '' . __('XCache') . ''; } else { - $this->data['accelerator'] = __('NA'); + $this->accelerator = __('NA'); } return $this; diff --git a/app/Models/Pages/Auth.php b/app/Models/Pages/Auth.php index 458d194d..022c9c47 100644 --- a/app/Models/Pages/Auth.php +++ b/app/Models/Pages/Auth.php @@ -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')]); } } diff --git a/app/Models/Pages/Ban.php b/app/Models/Pages/Ban.php index def7ddf7..8efc1544 100644 --- a/app/Models/Pages/Ban.php +++ b/app/Models/Pages/Ban.php @@ -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'); - - if (! empty($banned['expire'])) { - $banned['expire'] = strtolower($this->time($banned['expire'], true)); + $ban = $user->banInfo; + + 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() + { + } } diff --git a/app/Models/Pages/CrumbTrait.php b/app/Models/Pages/CrumbTrait.php index b3edf1f9..601fd27c 100644 --- a/app/Models/Pages/CrumbTrait.php +++ b/app/Models/Pages/CrumbTrait.php @@ -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; } // главная страница diff --git a/app/Models/Pages/Debug.php b/app/Models/Pages/Debug.php index fe394d78..94b07362 100644 --- a/app/Models/Pages/Debug.php +++ b/app/Models/Pages/Debug.php @@ -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 []; } } diff --git a/app/Models/Pages/Forum.php b/app/Models/Pages/Forum.php index 6bc3b27a..32d09a57 100644 --- a/app/Models/Pages/Forum.php +++ b/app/Models/Pages/Forum.php @@ -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) - || $user->isAdmin + $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; } diff --git a/app/Models/Pages/ForumsTrait.php b/app/Models/Pages/ForumsTrait.php index cce830b5..39f6a8a4 100644 --- a/app/Models/Pages/ForumsTrait.php +++ b/app/Models/Pages/ForumsTrait.php @@ -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, ]; } diff --git a/app/Models/Pages/Index.php b/app/Models/Pages/Index.php index 1db4dfcb..d177cf86 100644 --- a/app/Models/Pages/Index.php +++ b/app/Models/Pages/Index.php @@ -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,30 +19,32 @@ 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; } } diff --git a/app/Models/Pages/Install.php b/app/Models/Pages/Install.php index 33878fb5..94fc869f 100644 --- a/app/Models/Pages/Install.php +++ b/app/Models/Pages/Install.php @@ -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']); + $this->defaultStyles = $defaultStyles; + // типы БД - $dbTypes = $this->getDBTypes(isset($args['dbtype']) ? $args['dbtype'] : null); + $dbTypes = $this->DBTypes(isset($args['dbtype']) ? $args['dbtype'] : null); if (empty($dbTypes)) { - $this->iswev['e'][] = __('No DB extensions'); + $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']; } - 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->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(); diff --git a/app/Models/Pages/Maintenance.php b/app/Models/Pages/Maintenance.php index a6b8739d..18192fae 100644 --- a/app/Models/Pages/Maintenance.php +++ b/app/Models/Pages/Maintenance.php @@ -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, - ]; } } diff --git a/app/Models/Pages/OnlineTrait.php b/app/Models/Pages/OnlineTrait.php index 7b864ec6..bb47f920 100644 --- a/app/Models/Pages/OnlineTrait.php +++ b/app/Models/Pages/OnlineTrait.php @@ -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', [ diff --git a/app/Models/Pages/Post.php b/app/Models/Pages/Post.php new file mode 100644 index 00000000..1fae2e05 --- /dev/null +++ b/app/Models/Pages/Post.php @@ -0,0 +1,68 @@ +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; + } +} diff --git a/app/Models/Pages/Redirect.php b/app/Models/Pages/Redirect.php index 77503842..f7d1c567 100644 --- a/app/Models/Pages/Redirect.php +++ b/app/Models/Pages/Redirect.php @@ -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(); } } diff --git a/app/Models/Pages/Register.php b/app/Models/Pages/Register.php index 10d17781..0948e02e 100644 --- a/app/Models/Pages/Register.php +++ b/app/Models/Pages/Register.php @@ -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]); } } diff --git a/app/Models/Pages/Rules.php b/app/Models/Pages/Rules.php index 1acfb1ff..1b5922fc 100644 --- a/app/Models/Pages/Rules.php +++ b/app/Models/Pages/Rules.php @@ -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; } } diff --git a/app/Models/Pages/Topic.php b/app/Models/Pages/Topic.php index 14546fb1..c94ebb69 100644 --- a/app/Models/Pages/Topic.php +++ b/app/Models/Pages/Topic.php @@ -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 idc->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); } } } diff --git a/app/Models/Pages/UsersTrait.php b/app/Models/Pages/UsersTrait.php index 7aa23487..d51428bc 100644 --- a/app/Models/Pages/UsersTrait.php +++ b/app/Models/Pages/UsersTrait.php @@ -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}"; } } diff --git a/app/Models/SmileyList.php b/app/Models/SmileyList.php new file mode 100644 index 00000000..d4b2055b --- /dev/null +++ b/app/Models/SmileyList.php @@ -0,0 +1,23 @@ +c->Cache->has('smilies')) { + $this->list = $this->c->Cache->get('smilies'); + } else { + $this->load(); + } + return $this; + } +} diff --git a/app/Models/SmileyList/Load.php b/app/Models/SmileyList/Load.php new file mode 100644 index 00000000..83e5533a --- /dev/null +++ b/app/Models/SmileyList/Load.php @@ -0,0 +1,22 @@ +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; + } +} diff --git a/app/Models/Stats.php b/app/Models/Stats.php new file mode 100644 index 00000000..199bf3c4 --- /dev/null +++ b/app/Models/Stats.php @@ -0,0 +1,30 @@ +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; + } +} diff --git a/app/Models/Stats/Load.php b/app/Models/Stats/Load.php new file mode 100644 index 00000000..f2c30429 --- /dev/null +++ b/app/Models/Stats/Load.php @@ -0,0 +1,27 @@ +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; + } +} diff --git a/app/Models/Stopwords.php b/app/Models/Stopwords.php new file mode 100644 index 00000000..69248f1f --- /dev/null +++ b/app/Models/Stopwords.php @@ -0,0 +1,82 @@ +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; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index a652fab6..384f7d56 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -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; diff --git a/app/Models/User/IsUnique.php b/app/Models/User/IsUnique.php new file mode 100644 index 00000000..fb6d927f --- /dev/null +++ b/app/Models/User/IsUnique.php @@ -0,0 +1,26 @@ +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); + } +} diff --git a/app/Models/User/Load.php b/app/Models/User/Load.php new file mode 100644 index 00000000..b684a000 --- /dev/null +++ b/app/Models/User/Load.php @@ -0,0 +1,46 @@ +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]); + } +} diff --git a/app/Models/Actions/LoadUserFromCookie.php b/app/Models/User/LoadUserFromCookie.php similarity index 61% rename from app/Models/Actions/LoadUserFromCookie.php rename to app/Models/User/LoadUserFromCookie.php index 5d37f0c0..9aaead91 100644 --- a/app/Models/Actions/LoadUserFromCookie.php +++ b/app/Models/User/LoadUserFromCookie.php @@ -1,63 +1,44 @@ 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) { diff --git a/app/Models/User/Save.php b/app/Models/User/Save.php new file mode 100644 index 00000000..a5f56da7 --- /dev/null +++ b/app/Models/User/Save.php @@ -0,0 +1,71 @@ +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(); + } +} diff --git a/app/Models/User/UpdateLastVisit.php b/app/Models/User/UpdateLastVisit.php new file mode 100644 index 00000000..8d13a0d1 --- /dev/null +++ b/app/Models/User/UpdateLastVisit.php @@ -0,0 +1,19 @@ +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; + } + } +} diff --git a/app/Models/UserCookie.php b/app/Models/UserCookie.php deleted file mode 100644 index 42e0ed50..00000000 --- a/app/Models/UserCookie.php +++ /dev/null @@ -1,157 +0,0 @@ -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); - } - } -} diff --git a/app/Models/UserMapper.php b/app/Models/UserMapper.php deleted file mode 100644 index 076c02c3..00000000 --- a/app/Models/UserMapper.php +++ /dev/null @@ -1,177 +0,0 @@ -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(); - } -} diff --git a/app/bootstrap.php b/app/bootstrap.php index aef06f6b..9eb3245b 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -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('', $debug, $tpl); } exit($tpl); diff --git a/app/lang/English/common.po b/app/lang/English/common.po index 17f59541..a4fdb2b6 100644 --- a/app/lang/English/common.po +++ b/app/lang/English/common.po @@ -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 %1$s." msgid "Never" msgstr "Never" diff --git a/app/lang/Russian/common.po b/app/lang/Russian/common.po index d4b2a5f9..537af113 100644 --- a/app/lang/Russian/common.po +++ b/app/lang/Russian/common.po @@ -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 "Все возникшие вопросы отправляйте администратору форума по адресу %1$s." msgid "Never" msgstr "Нет" diff --git a/app/templates/admin/group.tpl b/app/templates/admin/group.tpl index 0890e14d..4947fe71 100644 --- a/app/templates/admin/group.tpl +++ b/app/templates/admin/group.tpl @@ -2,18 +2,18 @@

{!! __('Group settings head') !!}

-
- + +
-@foreach($form as $key => $cur) +@foreach($p->form as $key => $cur)
{!! $cur['title'] !!}
@if($cur['type'] == 'text') - + @elseif($cur['type'] == 'number') - + @elseif($cur['type'] == 'select') - @foreach($cur['options'] as $v => $n) @if($v == $cur['value']) @@ -25,9 +25,9 @@ @elseif($cur['type'] == 'radio') @foreach($cur['values'] as $v => $n) @if($v == $cur['value']) - + @else - + @endif @endforeach @endif @@ -37,11 +37,11 @@
@endforeach
-@if($warn) -

{!! $warn !!}

+@if($p->warn) +

{!! $p->warn !!}

@endif
- +
diff --git a/app/templates/admin/groups.tpl b/app/templates/admin/groups.tpl index 0b18534e..d98b08b0 100644 --- a/app/templates/admin/groups.tpl +++ b/app/templates/admin/groups.tpl @@ -2,14 +2,14 @@

{!! __('Add group subhead') !!}

-
- + +
{!! __('New group label') !!}
- +@foreach($p->groupsNew as $cur) +@if ($cur[0] == $p->defaultGroup) @else @@ -20,7 +20,7 @@
- +
@@ -28,14 +28,14 @@

{!! __('Default group subhead') !!}

-
- + +
{!! __('Default group label') !!}
- +@foreach($p->groupsDefault as $cur) +@if ($cur[0] == $p->defaultGroup) @else @@ -46,7 +46,7 @@
- +
@@ -56,11 +56,11 @@

{!! __('Edit groups info') !!}

    -@foreach($groupsList as $cur) +@foreach($p->groupsList as $cur)
  1. - {{ $cur[1] }} + {{ $cur[1] }} @if($cur[2]) - {!! __('Delete link') !!} + {!! __('Delete link') !!} @endif
  2. @endforeach diff --git a/app/templates/admin/index.tpl b/app/templates/admin/index.tpl index 010e707e..43a4089f 100644 --- a/app/templates/admin/index.tpl +++ b/app/templates/admin/index.tpl @@ -19,9 +19,9 @@
    {!! __('ForkBB version label') !!}
    -
    {!! __('ForkBB version data', $revision) !!}
    +
    {!! __('ForkBB version data', $p->revision) !!}
    {!! __('Server statistics label') !!}
    -
    {!! __('View server statistics') !!}
    +
    {!! __('View server statistics') !!}
    {!! __('Support label') !!}
    GitHub
    diff --git a/app/templates/admin/statistics.tpl b/app/templates/admin/statistics.tpl index 848751a2..cf2d5642 100644 --- a/app/templates/admin/statistics.tpl +++ b/app/templates/admin/statistics.tpl @@ -4,24 +4,24 @@
    {!! __('Server load label') !!}
    -
    {!! __('Server load data', $serverLoad, $numOnline) !!}
    -@if($isAdmin) +
    {!! __('Server load data', $p->serverLoad, $p->numOnline) !!}
    +@if($p->isAdmin)
    {!! __('Environment label') !!}
    {!! __('Environment data OS', PHP_OS) !!}
    - {!! __('Environment data version', phpversion(), ''.__('Show info').'') !!}
    - {!! __('Environment data acc', $accelerator) !!} + {!! __('Environment data version', phpversion(), ''.__('Show info').'') !!}
    + {!! __('Environment data acc', $p->accelerator) !!}
    {!! __('Database label') !!}
    - {{ $dbVersion }} -@if($tRecords && $tSize) -
    {!! __('Database data rows', $tRecords) !!} -
    {!! __('Database data size', $tSize) !!} + {{ $p->dbVersion }} +@if($p->tRecords && $p->tSize) +
    {!! __('Database data rows', $p->tRecords) !!} +
    {!! __('Database data size', $p->tSize) !!} @endif -@if($tOther) +@if($p->tOther)

    {!! __('Other')!!} -@foreach($tOther as $key => $value) +@foreach($p->tOther as $key => $value)
    {{ $key }} = {{ $value }} @endforeach @endif diff --git a/app/templates/ban.tpl b/app/templates/ban.tpl index 9f0ff9d1..9df6e4c3 100644 --- a/app/templates/ban.tpl +++ b/app/templates/ban.tpl @@ -2,12 +2,12 @@

    {{ __('Info') }}

    {!! __('Ban message') !!}

    -@if(! empty($banned['expire'])) -

    {!! __('Ban message 2') !!} {{ $banned['expire'] }}

    +@if(! empty($p->ban['expire'])) +

    {!! __('Ban message 2', $p->ban['expire']) !!}

    @endif -@if(! empty($banned['message'])) +@if(! empty($p->ban['message']))

    {!! __('Ban message 3') !!}

    -

    {{ $banned['message'] }}

    +

    {{ $p->ban['message'] }}

    @endif -

    {!! __('Ban message 4'] !!) {{ $adminEmail }}.

    +

    {!! __('Ban message 4', $p->adminEmail, $p->adminEmail) !!}

    diff --git a/app/templates/change_passphrase.tpl b/app/templates/change_passphrase.tpl index c52a537b..e6efae03 100644 --- a/app/templates/change_passphrase.tpl +++ b/app/templates/change_passphrase.tpl @@ -2,8 +2,8 @@