Code style and minor changes

This commit is contained in:
Visman 2023-04-29 15:07:09 +07:00
parent 14c3a5d0db
commit 0f61f3ec0d
100 changed files with 502 additions and 144 deletions

View file

@ -24,16 +24,12 @@ class Install
*/
public function routing(): Page
{
$uri = $_SERVER['REQUEST_URI'];
if (false !== ($pos = \strpos($uri, '?'))) {
$uri = \substr($uri, 0, $pos);
}
$uri = \rawurldecode($uri);
$this->c->user = $this->c->users->create(['id' => 1, 'group_id' => FORK_GROUP_ADMIN]);
$this->c->Lang->load('common');
$r = $this->c->Router;
$r->add(
$r::DUO,
'/admin/install',
@ -41,18 +37,27 @@ class Install
'Install'
);
$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
if (false !== ($pos = \strpos($uri, '?'))) {
$uri = \substr($uri, 0, $pos);
}
$uri = \rawurldecode($uri);
$method = $_SERVER['REQUEST_METHOD'];
$route = $r->route($method, $uri);
$page = null;
$route = $r->route($method, $uri);
$page = null;
switch ($route[0]) {
case $r::OK:
// ... 200 OK
list($page, $action) = \explode(':', $route[1], 2);
$page = $this->c->$page->$action($route[2], $method);
break;
default:
$page = $this->c->Redirect->page('Install')->message('Redirect to install');
break;
}

View file

@ -716,19 +716,22 @@ class Routing
}
$uri = $_SERVER['REQUEST_URI'];
if (false !== ($pos = \strpos($uri, '?'))) {
$uri = \substr($uri, 0, $pos);
}
$uri = \rawurldecode($uri);
$method = $_SERVER['REQUEST_METHOD'];
$route = $r->route($method, $uri);
$page = null;
$route = $r->route($method, $uri);
$page = null;
switch ($route[0]) {
case $r::OK:
// ... 200 OK
list($page, $action) = \explode(':', $route[1], 2);
$page = $this->c->$page->$action($route[2], $method);
break;
case $r::NOT_FOUND:
// ... 404 Not Found
@ -740,6 +743,7 @@ class Routing
} else {
$page = $this->c->Message->message('Not Found', true, 404);
}
break;
case $r::METHOD_NOT_ALLOWED:
// ... 405 Method Not Allowed
@ -751,10 +755,12 @@ class Routing
['Allow', \implode(',', $route[1])],
]
);
break;
case $r::NOT_IMPLEMENTED:
// ... 501 Not implemented
$page = $this->c->Message->message('Bad request', true, 501);
break;
}

View file

@ -24,16 +24,12 @@ class Update
*/
public function routing(): Page
{
$uri = $_SERVER['REQUEST_URI'];
if (false !== ($pos = \strpos($uri, '?'))) {
$uri = \substr($uri, 0, $pos);
}
$uri = \rawurldecode($uri);
$this->c->user = $this->c->users->create(['id' => 1, 'group_id' => FORK_GROUP_ADMIN]); //???? id?
$this->c->Lang->load('common');
$r = $this->c->Router;
$r->add(
$r::GET,
'/admin/update/{uid}/{stage|i:\d+}[/{start|i:\d+}]',
@ -47,18 +43,27 @@ class Update
'AdminUpdate'
);
$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
if (false !== ($pos = \strpos($uri, '?'))) {
$uri = \substr($uri, 0, $pos);
}
$uri = \rawurldecode($uri);
$method = $_SERVER['REQUEST_METHOD'];
$route = $r->route($method, $uri);
$page = null;
$route = $r->route($method, $uri);
$page = null;
switch ($route[0]) {
case $r::OK:
// ... 200 OK
list($page, $action) = \explode(':', $route[1], 2);
$page = $this->c->$page->$action($route[2], $method);
break;
default:
$page = $this->c->AdminUpdate->view([], 'GET');
break;
}

View file

@ -24,9 +24,8 @@ class FileCache implements CacheInterface
{
/**
* Директория кэша
* @var string
*/
protected $cacheDir;
protected string $cacheDir;
public function __construct(string $dir, string $resetMark)
{

View file

@ -227,9 +227,9 @@ class Func
foreach (\explode(',', $str) as $step) {
$dsr = \explode(';', $step, 2);
if (
isset($dsr[1])) {
if (isset($dsr[1])) {
$q = \trim(\ltrim(\ltrim($dsr[1], 'q '), '='));
if (
! \is_numeric($q)
|| $q < 0
@ -237,6 +237,7 @@ class Func
) {
continue;
}
$q = (float) $q;
} else {
$q = 1;

View file

@ -245,6 +245,7 @@ class Lang
$curComm = null;
$curVal = '';
$cur = [];
continue;
// комментарий
@ -256,6 +257,7 @@ class Lang
if (isset($curComm)) {
$curVal .= $this->originalLine($line);
}
continue;
// промежуточные данные

View file

@ -150,6 +150,7 @@ class Router
|| 1 !== $args[$name]
) {
$data['{' . $name . '}'] = \rawurlencode(\str_replace($this->subSearch, $this->subRepl, (string) $args[$name]));
continue;
}
}
@ -248,6 +249,7 @@ class Router
list($handler, $keys, $marker) = $data['GET'];
} else {
$allowed += \array_keys($data);
continue;
}

View file

@ -16,8 +16,6 @@ use RuntimeException;
class View extends Dirk
{
protected $templates = [];
public function __construct (string $cache, string $views)
{
$config = [

View file

@ -15,6 +15,8 @@ use RuntimeException;
class AdminList extends Model
{
const CACHE_KEY = 'admins';
/**
* Ключ модели для контейнера
*/
@ -26,12 +28,12 @@ class AdminList extends Model
*/
public function init(): AdminList
{
$this->list = $this->c->Cache->get('admins');
$this->list = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($this->list)) {
$this->list = \array_flip($this->c->users->adminsIds());
if (true !== $this->c->Cache->set('admins', $this->list)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $this->list)) {
throw new RuntimeException('Unable to write value to cache - admins');
}
}
@ -44,7 +46,7 @@ class AdminList extends Model
*/
public function reset(): AdminList
{
if (true !== $this->c->Cache->delete('admins')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - admins');
}

View file

@ -12,7 +12,6 @@ namespace ForkBB\Models\BBCodeList;
use ForkBB\Models\Method;
use ForkBB\Models\BBCodeList\BBCodeList;
use PDO;
class Delete extends Method
{

View file

@ -27,6 +27,7 @@ class Generate extends Method
$content = "<?php\n\nuse function \\ForkBB\\{__, url};\n\nreturn [\n";
$stmt = $this->c->DB->query($query);
while ($row = $stmt->fetch()) {
$content .= " [\n"
. $this->addArray(\json_decode($row['bb_structure'], true, 512, \JSON_THROW_ON_ERROR))
@ -56,12 +57,15 @@ class Generate extends Method
switch ($type) {
case 'NULL':
$value = 'null';
break;
case 'boolean':
$value = $value ? 'true' : 'false';
break;
case 'array':
$value = "[\n" . $this->addArray($value, $level + 1) . "{$space}]";
break;
case 'double':
case 'integer':
@ -78,10 +82,10 @@ class Generate extends Method
} else {
$value = '\'' . \addslashes($value) . '\'';
}
break;
default:
throw new RuntimeException("Invalid data type ({$type})");
break;
}
if (\is_string($key)) {

View file

@ -32,7 +32,7 @@ class Structure extends Model
parent::__construct($container);
$this->zDepend = [
'attrs' => ['no_attr', 'def_attr', 'other_attrs'],
'attrs' => ['no_attr', 'def_attr', 'other_attrs'],
];
}
@ -237,10 +237,12 @@ class Structure extends Model
case 'format':
case 'body_format':
$value = isset($data[$field]) && \is_string($data[$field]) ? $data[$field] : null;
break;
case 'required':
case 'text_only':
$value = isset($data[$field]) ? true : null;
break;
default:
throw new RuntimeException('Unknown attribute property');
@ -264,15 +266,18 @@ class Structure extends Model
unset($attrs[$name]);
} else {
$result = [];
foreach ($fields as $field) {
switch ($field) {
case 'format':
case 'body_format':
$value = ! empty($data[$field]) && \is_string($data[$field]) ? $data[$field] : null;
break;
case 'required':
case 'text_only':
$value = ! empty($data[$field]) ? true : null;
break;
default:
throw new RuntimeException('Unknown attribute property');
@ -320,6 +325,7 @@ class Structure extends Model
unset($attrs['No_attr'], $attrs['Def'], $attrs['New']);
$result = [];
foreach ($attrs as $name => $attr) {
$value = $this->getBBAttr($name, ['required', 'format', 'body_format', 'text_only']);
@ -353,11 +359,13 @@ class Structure extends Model
}
$result = $this->testPHP($this->handler);
if (null !== $result) {
return ['PHP code error in Handler: %s', $result];
}
$result = $this->testPHP($this->text_handler);
if (null !== $result ) {
return ['PHP code error in Text handler: %s', $result];
}
@ -486,6 +494,7 @@ class Structure extends Model
// тест на парность скобок
$testCode = \preg_replace('%//[^\r\n]*+|#[^\r\n]*+|/\*.*?\*/|\'.*?(?<!\\\\)\'|".*?(?<!\\\\)"%s', '', $code);
if (false === \preg_match_all('%[(){}\[\]]%s', $testCode, $matches)) {
throw new RuntimeException('The preg_match_all() returned an error');
}
@ -498,6 +507,7 @@ class Structure extends Model
switch ($value) {
case '(':
++$round;
break;
case ')':
--$round;
@ -505,9 +515,11 @@ class Structure extends Model
if ($round < 0) {
return '\')\' > \'(\'.';
}
break;
case '[':
++$square;
break;
case ']':
--$square;
@ -515,9 +527,11 @@ class Structure extends Model
if ($square < 0) {
return '\']\' > \'[\'.';
}
break;
case '{':
++$curly;
break;
case '}':
--$curly;
@ -525,6 +539,7 @@ class Structure extends Model
if ($curly < 0) {
return '\'}\' > \'{\'.';
}
break;
default:
throw new RuntimeException('Unknown bracket type');

View file

@ -16,6 +16,8 @@ use RuntimeException;
class BanList extends Model
{
const CACHE_KEY = 'banlist';
/**
* Ключ модели для контейнера
*/
@ -27,12 +29,12 @@ class BanList extends Model
*/
public function init(): BanList
{
$list = $this->c->Cache->get('banlist');
$list = $this->c->Cache->get(self::CACHE_KEY);
if (! isset($list['banList'], $list['userList'], $list['emailList'], $list['ipList'], $list['firstExpire'])) {
$list = $this->load();
if (true !== $this->c->Cache->set('banlist', $list)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $list)) {
throw new RuntimeException('Unable to write value to cache - banlist');
}
}
@ -96,7 +98,7 @@ class BanList extends Model
*/
public function reset(): BanList
{
if (true !== $this->c->Cache->delete('banlist')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - banlist');
}

View file

@ -50,6 +50,7 @@ class Filter extends Method
if (! isset($fields[$field])) {
throw new InvalidArgumentException("The '{$field}' field is not found");
}
switch ($rule[0]) {
case 'LIKE':
if (
@ -61,13 +62,16 @@ class Filter extends Method
$where[] = "b.{$field} {$like} ?{$fields[$field]} ESCAPE '#'";
$vars[] = \str_replace(['#', '%', '_', '*'], ['##', '#%', '#_', '%'], $rule[1]);
}
break;
}
$rule[0] = '=';
case '=':
case '!=':
$where[] = "b.{$field}{$rule[0]}?{$fields[$field]}";
$vars[] = $rule[1];
break;
case 'BETWEEN':
// если и min, и max
@ -96,6 +100,7 @@ class Filter extends Method
$where[] = "b.{$field}<=?{$fields[$field]}";
$vars[] = $rule[2];
}
break;
default:
throw new InvalidArgumentException('The condition is not defined');

View file

@ -48,13 +48,15 @@ class IsBanned extends Method
if (false !== $pos) {
$email = \substr($email, $pos + 1); // -> example.com
break;
}
++$stage;
case 1:
$email = '.' . $email; // -> .example.com
$pos = true;
$pos = true;
break;
default:
$pos = \strpos($email, '.', 1);

View file

@ -31,19 +31,23 @@ class Load extends Method
FROM ::bans AS b';
$stmt = $this->c->DB->query($query);
while ($row = $stmt->fetch()) {
$name = $this->model->trimToNull($row['username'], true);
if (null !== $name) {
$userList[$name] = $row['id'];
}
$email = $this->model->trimToNull($row['email']);
if (null !== $email) {
$email = $this->c->NormEmail->normalize($email);
$emailList[$email] = $row['id']; // ???? TODO если домен забанен, то email не добавлять
}
$ips = $this->model->trimToNull($row['ip']);
if (null !== $ips) {
foreach (\explode(' ', $ips) as $ip) {
$list = &$ipList;

View file

@ -82,6 +82,7 @@ class Categories extends Manager
$this->c->DB->exec($query, $vars);
}
$this->modified = [];
return $this;
@ -90,11 +91,13 @@ class Categories extends Manager
public function insert(string $name): int
{
$pos = 0;
foreach ($this->repository as $cat) {
if ($cat['disp_position'] > $pos) {
$pos = $cat['disp_position'];
}
}
++$pos;
$vars = [
@ -105,7 +108,9 @@ class Categories extends Manager
VALUES (?s:name, ?i:position)';
$this->c->DB->exec($query, $vars);
$cid = (int) $this->c->DB->lastInsertId();
parent::set($cid, ['cat_name' => $name, 'disp_position' => $pos]);
return $cid;

View file

@ -15,6 +15,8 @@ use RuntimeException;
class Censorship extends Model
{
const CACHE_KEY = 'censorship';
/**
* Ключ модели для контейнера
*/
@ -27,12 +29,12 @@ class Censorship extends Model
public function init(): Censorship
{
if (1 === $this->c->config->b_censoring) {
$list = $this->c->Cache->get('censorship');
$list = $this->c->Cache->get(self::CACHE_KEY);
if (! isset($list['searchList'], $list['replaceList'])) {
$list = $this->refresh();
if (true !== $this->c->Cache->set('censorship', $list)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $list)) {
throw new RuntimeException('Unable to write value to cache - censorship');
}
}
@ -61,7 +63,7 @@ class Censorship extends Model
*/
public function reset(): Censorship
{
if (true !== $this->c->Cache->delete('censorship')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - censorship');
}

View file

@ -24,6 +24,7 @@ class Save extends Method
{
$words = $this->model->load();
$forDel = [];
foreach ($list as $id => $row) {
if (! isset($list[$id]['search_for'], $list[$id]['replace_with'])) {
continue;

View file

@ -15,6 +15,8 @@ use RuntimeException;
class Config extends DataModel
{
const CACHE_KEY = 'config';
/**
* Ключ модели для контейнера
*/
@ -26,12 +28,12 @@ class Config extends DataModel
*/
public function init(): Config
{
$config = $this->c->Cache->get('config');
$config = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($config)) {
$config = $this->load();
if (true !== $this->c->Cache->set('config', $config)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $config)) {
throw new RuntimeException('Unable to write value to cache - config');
}
}
@ -46,7 +48,7 @@ class Config extends DataModel
*/
public function reset(): Config
{
if (true !== $this->c->Cache->delete('config')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - config');
}

View file

@ -14,12 +14,14 @@ use ForkBB\Models\Method;
class Insensitive extends Method
{
const CACHE_KEY = 'case_insensitive';
/**
* Проверяет регистронезависимое сравнение в БД через таблицу config
*/
public function insensitive(): bool
{
$result = $this->c->Cache->get('case_insensitive', null);
$result = $this->c->Cache->get(self::CACHE_KEY, null);
if (! \is_bool($result)) {
$like = 'pgsql' === $this->c->DB->getType() ? 'ILIKE' : 'LIKE';
@ -29,7 +31,7 @@ class Insensitive extends Method
$result = 'Ok' === $this->c->DB->query($query)->fetchColumn();
if (true !== $this->c->Cache->set('case_insensitive', $result)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $result)) {
throw new RuntimeException('Unable to write value to cache - case_insensitive');
}
}

View file

@ -12,8 +12,6 @@ namespace ForkBB\Models\Config;
use ForkBB\Models\Method;
use ForkBB\Models\Config\Config;
use PDO;
use RuntimeException;
class Load extends Method
{
@ -27,21 +25,26 @@ class Load extends Method
FROM ::config AS cf';
$stmt = $this->c->DB->query($query);
while ($row = $stmt->fetch()) {
switch ($row['conf_name'][0]) {
case 'a':
$value = \json_decode($row['conf_value'], true, 512, \JSON_THROW_ON_ERROR);
break;
case 'b':
$value = '1' == $row['conf_value'] ? 1 : 0;
break;
case 'i':
if (null !== $row['conf_value']) {
$value = (int) $row['conf_value'];
break;
}
default:
$value = $row['conf_value'];
break;
}

View file

@ -22,27 +22,33 @@ class Save extends Method
public function save(): Config
{
$modified = $this->model->getModified();
if (empty($modified)) {
return $this->model;
}
$values = $this->model->getAttrs();
foreach ($modified as $name) {
if (\array_key_exists($name, $values)) {
switch ($name[0]) {
case 'a':
$value = \json_encode($values[$name], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR);
break;
case 'b':
$value = $values[$name] ? '1' : '0';
break;
case 'i':
if (null !== $values[$name]) {
$value = (string) $values[$name];
break;
}
default:
$value = $values[$name];
break;
}

View file

@ -99,6 +99,7 @@ class Cookie extends Model
public function delete(string $name, string $path = null, string $domain = null): bool
{
$result = $this->set($name, '', 1, $path, $domain);
if ($result) {
unset($_COOKIE[$this->prefix . $name]);
}
@ -173,6 +174,7 @@ class Cookie extends Model
$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);
@ -203,6 +205,7 @@ class Cookie extends Model
if ($this->noSet) {
throw new RuntimeException('Model attributes in read-only mode');
}
parent::__set($name, $val);
}
}

View file

@ -15,6 +15,8 @@ use RuntimeException;
class DBMap extends Model
{
const CACHE_KEY = 'db_map';
/**
* Ключ модели для контейнера
*/
@ -25,12 +27,12 @@ class DBMap extends Model
*/
public function init(): DBMap
{
$map = $this->c->Cache->get('db_map');
$map = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($map)) {
$map = $this->c->DB->getMap();
if (true !== $this->c->Cache->set('db_map', $map)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $map)) {
throw new RuntimeException('Unable to write value to cache - db_map');
}
}
@ -45,7 +47,7 @@ class DBMap extends Model
*/
public function reset(): DBMap
{
if (true !== $this->c->Cache->delete('db_map')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - db_map');
}

View file

@ -17,6 +17,8 @@ use RuntimeException;
class Forums extends Manager
{
const CACHE_KEY = 'forums_mark';
/**
* Ключ модели для контейнера
*/
@ -47,12 +49,12 @@ class Forums extends Manager
$gid = $group->g_id;
}
$mark = $this->c->Cache->get('forums_mark');
$mark = $this->c->Cache->get(self::CACHE_KEY);
if (empty($mark)) {
$mark = \time();
if (true !== $this->c->Cache->set('forums_mark', $mark)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $mark)) {
throw new RuntimeException('Unable to write value to cache - forums_mark');
}
@ -91,6 +93,7 @@ class Forums extends Manager
if (empty($this->forumList[$id])) {
return null;
}
$forum = $this->create($this->forumList[$id]);
$this->set($id, $forum);
}
@ -123,6 +126,7 @@ class Forums extends Manager
public function depthList(Forum $forum, int $depth, array $list = []): array
{
++$depth;
foreach ($forum->subforums as $sub) {
$sub->__depth = $depth;
$list[] = $sub;
@ -138,7 +142,7 @@ class Forums extends Manager
*/
public function reset(): Forums
{
if (true !== $this->c->Cache->delete('forums_mark')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - forums_mark');
}

View file

@ -21,11 +21,13 @@ class LoadTree extends Action
public function loadTree(int $rootId): ?Forum
{
$root = $this->manager->get($rootId);
if (null === $root) {
return null;
}
$list = [];
if (! $root->ready) {
$list[$rootId] = $root;
}
@ -81,6 +83,7 @@ class LoadTree extends Action
}
$stmt = $this->c->DB->query($query, $vars);
while ($cur = $stmt->fetch()) {
$list[$cur['id']]->replAttrs($cur)->__ready = true;
}
@ -101,6 +104,7 @@ class LoadTree extends Action
// предварительная проверка разделов
$time = [];
$max = \max((int) $this->c->user->last_visit, (int) $this->c->user->u_mark_all_read);
foreach ($list as $forum) {
$t = \max($max, (int) $forum->mf_mark_all_read);
if ($forum->last_post > $t) {
@ -127,6 +131,7 @@ class LoadTree extends Action
AND (mot.mt_last_visit IS NULL OR t.last_post>mot.mt_last_visit)';
$stmt = $this->c->DB->query($query, $vars);
while ($cur = $stmt->fetch()) {
if ($cur['last_post'] > $time[$cur['forum_id']]) {
$list[$cur['forum_id']]->__newMessages = true; //????

View file

@ -46,6 +46,7 @@ class Refresh extends Action
ORDER BY c.disp_position, c.id, f.disp_position';
$stmt = $this->c->DB->query($query, $vars);
while ($row = $stmt->fetch()) {
$row['moderators'] = $this->formatModers($row['moderators']);
$list[$row['id']] = $row;
@ -76,6 +77,7 @@ class Refresh extends Action
{
$sub = [];
$all = [];
foreach ($list as $id => $f) {
if (
$parent === $id
@ -83,6 +85,7 @@ class Refresh extends Action
) {
continue;
}
$sub[] = $id;
$all = \array_merge($this->createList($list, $id), $all);
}
@ -90,9 +93,11 @@ class Refresh extends Action
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;

View file

@ -24,23 +24,30 @@ class Save extends Action
if ($forum->id < 1) {
throw new RuntimeException('The model does not have ID');
}
$modified = $forum->getModified();
if (empty($modified)) {
return $forum;
}
$values = $forum->getAttrs();
$fileds = $this->c->dbMap->forums;
$set = $vars = [];
foreach ($modified as $name) {
if (! isset($fileds[$name])) {
continue;
}
$vars[] = $values[$name];
$set[] = $name . '=?' . $fileds[$name];
}
if (empty($set)) {
return $forum;
}
$vars[] = $forum->id;
$query = 'UPDATE ::forums
SET ' . \implode(', ', $set) . ' WHERE id=?i';
@ -55,6 +62,7 @@ class Save extends Action
foreach ($forum->descendants as $f) {
$f->__cat_id = $values['cat_id'];
}
$vars = [
':ids' => \array_keys($forum->descendants),
':category' => $values['cat_id'],
@ -79,17 +87,21 @@ class Save extends Action
if (null !== $forum->id) {
throw new RuntimeException('The model has ID');
}
$attrs = $forum->getAttrs();
$fileds = $this->c->dbMap->forums;
$set = $set2 = $vars = [];
foreach ($attrs as $key => $value) {
if (! isset($fileds[$key])) {
continue;
}
$vars[] = $value;
$set[] = $key;
$set2[] = '?' . $fileds[$key];
}
if (empty($set)) {
throw new RuntimeException('The model is empty');
}

View file

@ -49,9 +49,11 @@ class Groups extends Manager
ORDER BY g.g_id';
$stmt = $this->c->DB->query($query);
while ($row = $stmt->fetch()) {
$this->set($row['g_id'], $this->create($row));
}
$this->flag = true;
}

View file

@ -38,6 +38,7 @@ class Perm extends Action
$perms = $this->c->DB->query($query, $vars)->fetchAll(PDO::FETCH_UNIQUE);
$result = [];
foreach ($perms as $gid => $perm) {
$group = $this->c->groups->get($gid);
# $forums = $this->c->ForumManager->init($group);
@ -53,6 +54,7 @@ class Perm extends Action
$result[$gid] = $group;
}
$this->fields = \array_keys($perm);
return $result;
@ -75,6 +77,7 @@ class Perm extends Action
$row = [];
$modDef = false;
$modPerm = false;
foreach ($this->fields as $field) {
if ($group->{'dis_' . $field}) {
$row[$field] = $group->{'set_' . $field} ? 1 : 0;

View file

@ -68,10 +68,11 @@ abstract class Page extends Model
$this->fTitle = $container->config->o_board_title;
$this->fDescription = $container->config->o_board_desc;
$this->fRootLink = $container->Router->link('Index');
if (1 === $container->config->b_announcement) {
$this->fAnnounce = $container->config->o_announcement_message;
}
$this->user = $this->c->user; // передача текущего юзера в шаблон
$this->user = $this->c->user; // передача текущего юзера в шаблон
$this->pageHeader('mainStyle', 'link', 10000, [
'rel' => 'stylesheet',
@ -251,6 +252,7 @@ abstract class Page extends Model
// 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;
@ -301,6 +303,7 @@ abstract class Page extends Model
if (empty($titles)) {
$titles = $this->titles;
}
$titles[] = ['%s', $this->c->config->o_board_title];
return \implode(__('Title separator'), \array_map('\\ForkBB\\__', $titles));
@ -367,9 +370,9 @@ abstract class Page extends Model
if (
! empty($_SERVER['SERVER_PROTOCOL'])
&& 'HTTP/' === \strtoupper(\substr($_SERVER['SERVER_PROTOCOL'], 0, 5))
&& \in_array($_SERVER['SERVER_PROTOCOL'], ['HTTP/1.1', 'HTTP/2', 'HTTP/3'], true)
) {
$header = 'HTTP/' . \substr($_SERVER['SERVER_PROTOCOL'], 5);
$header = $_SERVER['SERVER_PROTOCOL'];
}
} else {
$header .= ':';
@ -434,8 +437,9 @@ abstract class Page extends Model
*/
public function settitles(string|array $value): void
{
$attr = $this->getAttr('titles', []);
$attr = $this->getAttr('titles', []);
$attr[] = $value;
$this->setAttr('titles', $attr);
}

View file

@ -16,10 +16,7 @@ use function \ForkBB\__;
abstract class Admin extends Page
{
/**
* @var array
*/
protected $aCrumbs = [];
protected array $aCrumbs = [];
public function __construct(Container $container)
{

View file

@ -37,6 +37,7 @@ class Bans extends Admin
protected function encodeData(array $data): string
{
unset($data['token']);
$data = \base64_encode(\json_encode($data));
$hash = $this->c->Secury->hash($data);
@ -108,6 +109,7 @@ class Bans extends Admin
$this->formSearch = $this->formSearch($v->getData());
} else {
$this->formSearch = $this->formSearch($data);
if (empty($data)) {
$this->formBan = $this->formBan();
}
@ -356,13 +358,14 @@ class Bans extends Admin
public function result(array $args, string $method): Page
{
$data = $this->decodeData($args['data']);
if (false === $data) {
return $this->c->Message->message('Bad request');
}
$idsN = $this->forFilter($data);
$idsN = $this->forFilter($data);
$number = \count($idsN);
if (0 == $number) {
$this->fIswev = ['i', 'No bans found'];
@ -545,12 +548,15 @@ class Bans extends Admin
if (! empty($args['ids'])) {
$ids = \explode('-', $args['ids']);
foreach ($ids as &$id) {
if (! \preg_match('%^([2-9]|[1-9]\d+)$%D', $id)) {
return $this->c->Message->message('Bad request');
}
$id = (int) $id;
}
unset($id);
$this->banCount = \count($ids);

View file

@ -42,6 +42,7 @@ class Categories extends Admin
foreach ($v->form as $key => $row) {
$this->c->categories->set($key, $row);
}
$this->c->categories->update();
if (\strlen($v->new) > 0) {
@ -144,6 +145,7 @@ class Categories extends Admin
public function delete(array $args, string $method): Page
{
$category = $this->c->categories->get($args['id']);
if (! $category) {
return $this->c->Message->message('Bad request');
}

View file

@ -97,6 +97,7 @@ class Censoring extends Admin
];
$fieldset = [];
foreach ($this->c->censorship->load() as $id => $row) {
$fieldset["form[{$id}][search_for]"] = [
'class' => ['censor'],
@ -113,6 +114,7 @@ class Censoring extends Admin
'caption' => 'Replacement label',
];
}
$fieldset["form[0][search_for]"] = [
'class' => ['censor'],
'type' => 'text',

View file

@ -30,6 +30,7 @@ class Forums extends Admin
];
$idxs = [];
$root = $this->c->forums->get(0);
if ($root instanceof Forum) {
foreach ($this->c->forums->depthList($root, 0) as $f) {
if ($cid !== $f->cat_id) {
@ -53,10 +54,12 @@ class Forums extends Admin
}
}
}
foreach ($categories as $key => $row) {
$idxs[] = -$key;
$options[] = [-$key, __('Category prefix') . $row['cat_name']];
}
$this->listOfIndexes = $idxs;
$this->listForOptions = $options;
}
@ -77,6 +80,7 @@ class Forums extends Admin
}
$max = 0;
foreach ($root->descendants as $f) {
if ($f->disp_position > $max) {
$max = $f->disp_position;
@ -225,6 +229,7 @@ class Forums extends Admin
public function delete(array $args, string $method): Page
{
$forum = $this->c->forums->get($args['id']);
if (
! $forum instanceof Forum
|| $forum->subforums
@ -254,7 +259,6 @@ class Forums extends Admin
}
$this->c->forums->delete($forum);
$this->c->forums->reset();
return $this->c->Redirect->page('AdminForums')->message('Forum deleted redirect');
@ -381,6 +385,7 @@ class Forums extends Admin
$forum->sort_by = $v->sort_by;
$forum->redirect_url = $v->redirect_url ?? '';
$forum->no_sum_mess = $v->no_sum_mess;
if ($v->parent > 0) {
$forum->parent_forum_id = $v->parent;
$forum->cat_id = $this->c->forums->get($v->parent)->cat_id;
@ -513,6 +518,7 @@ class Forums extends Admin
$aOn = ['cando', 'on'];
$aOff = ['cando', 'off'];
foreach ($this->c->groups->Perm->get($forum) as $id => $group) {
$fields = [];
$fields["perms[{$id}][read_forum]"] = [

View file

@ -38,6 +38,7 @@ class Groups extends Admin
if (! \in_array($group->g_id, $notForNew, true)) {
$groupsNew[$key] = $group->g_title;
}
if (
! \in_array($group->g_id, $notForDefault, true)
&& 0 === $group->g_moderator
@ -150,6 +151,7 @@ class Groups extends Admin
return $this->view();
}
$this->c->config->i_default_user_group = $v->defaultgroup;
$this->c->config->save();
@ -327,6 +329,7 @@ class Groups extends Admin
$data['g_mod_promote_users'] = 0;
$data['g_mod_ban_users'] = 0;
}
if (
isset($data['g_promote_next_group'])
&& 0 == $data['g_promote_next_group'] * $data['g_promote_min_posts']
@ -762,8 +765,10 @@ class Groups extends Admin
$count = $this->c->users->usersNumber($group);
$groups = [];
if ($count) {
$move = 'required|integer|in:';
foreach ($this->groupsList as $key => $cur) {
if (
$key === FORK_GROUP_GUEST
@ -771,8 +776,10 @@ class Groups extends Admin
) {
continue;
}
$groups[$key] = $cur[0];
}
$move .= \implode(',', \array_keys($groups));
} else {
$move = 'absent';

View file

@ -29,9 +29,8 @@ class Install extends Admin
/**
* Для MySQL
* @var string
*/
protected $DBEngine = '';
protected string $DBEngine = '';
/**
* Подготовка страницы к отображению
@ -54,15 +53,19 @@ class Install extends Admin
case 'mysql':
$dbTypes['mysql_innodb'] = 'MySQL InnoDB (PDO)';
$dbTypes[$type] = 'MySQL (PDO) (no transactions!)';
break;
case 'sqlite':
$dbTypes[$type] = 'SQLite (PDO)';
break;
case 'pgsql':
$dbTypes[$type] = 'PostgreSQL (PDO)';
break;
default:
$dbTypes[$type] = \ucfirst($type) . ' (PDO)';
break;
}
}

View file

@ -58,6 +58,7 @@ class Logs extends Admin
]
);
}
unset($cur);
$this->nameTpl = 'admin/logs';

View file

@ -124,6 +124,7 @@ class Options extends Admin
if (empty($data['changeSmtpPassword'])) {
unset($data['o_smtp_pass']);
}
unset($data['changeSmtpPassword'], $data['token']);
foreach ($data as $attr => $value) {

View file

@ -64,28 +64,33 @@ class BBCode extends Parser
if (! isset($bbcode[$tag]['in_mes'], $bbcode[$tag]['in_sig'])) {
$mesClear = false;
$sigClear = false;
continue;
}
switch ($bbcode[$tag]['in_mes']) {
case 2:
$white_mes[] = $tag;
break;
case 0:
$black_mes[] = $tag;
default:
$mesClear = false;
break;
}
switch ($bbcode[$tag]['in_sig']) {
case 2:
$white_sig[] = $tag;
break;
case 0:
$black_sig[] = $tag;
default:
$sigClear = false;
break;
}
}
@ -322,6 +327,7 @@ class BBCode extends Parser
$structure = $this->c->BBStructure;
$id = $args['id'] ?? 0;
if ($id > 0) {
if (
empty($this->c->bbcode->bbcodeTable[$id])
@ -335,11 +341,13 @@ class BBCode extends Parser
$bbTypes = [];
$bbNames = [];
foreach ($this->c->bbcode->bbcodeTable as $cur) {
$type = $this->c->BBStructure->fromString($cur['bb_structure'])->type;
$bbTypes[$type] = $type;
$bbNames[$cur['bb_tag']] = $cur['bb_tag'];
}
$this->bbTypes = $bbTypes;
if ($id > 0) {
@ -351,6 +359,7 @@ class BBCode extends Parser
$page = 'AdminBBCodeNew';
$pageArgs = [];
}
$this->formAction = $this->c->Router->link($page, $pageArgs);
$this->formToken = $this->c->Csrf->create($page, $pageArgs);
@ -448,6 +457,7 @@ class BBCode extends Parser
}
$data = $v->getData();
unset($data['token'], $data['save']);
foreach ($data as $key => $value) {
@ -681,6 +691,7 @@ class BBCode extends Parser
'caption' => 'Allowed label',
'help' => $info,
];
if ('no_attr' !== $name) {
$fields["{$key}[required]"] = [
'type' => 'radio',

View file

@ -21,15 +21,13 @@ class Smilies extends Parser
{
/**
* Паттерн для имени изображения
* @var string
*/
protected $pattern = '%^[a-z0-9-_]+\.(?:gif|jpe?g|png|webp)$%isD';
protected string $pattern = '%^[a-z0-9-_]+\.(?:gif|jpe?g|png|webp)$%isD';
/**
* Паттерн для доступных к загрузке типов файлов
* @var string
*/
protected $accept = 'image/*';
protected string $accept = 'image/*';
/**
* Заполняет список файлов из каталога смайлов
@ -51,6 +49,7 @@ class Smilies extends Parser
$result[] = $entry;
}
}
\closedir($dh);
\sort($result, \SORT_NATURAL);
}
@ -157,6 +156,7 @@ class Smilies extends Parser
$i = 1;
$max = 0;
foreach ($this->c->smilies->list as $id => $cur) {
$fields = [];
$max = \max($max, $cur['sm_position']);

View file

@ -19,8 +19,8 @@ use function \ForkBB\dt;
class Reports extends Admin
{
protected $userIds = [];
protected $postIds = [];
protected array $userIds = [];
protected array $postIds = [];
/**
* Выделяет данные из списка сигналов
@ -85,6 +85,7 @@ class Reports extends Admin
'legend' => ['Marked as read %1$s by %2$s', dt($report->zapped), $report->marker->username],
];
}
$cur['fields'] = [];
$author = $report->author;
$cur['fields']['report_by' . $report->id] = [
@ -95,6 +96,7 @@ class Reports extends Admin
'href' => $author->link,
];
$post = $report->post;
if ($post instanceof Post) {
$topic = $post->parent;
$forum = $topic->parent;
@ -109,12 +111,14 @@ class Reports extends Admin
'value' => __(['Post #%s', $report->post_id]),
];
}
$cur['fields']['reason' . $report->id] = [
'class' => ['reason'],
'type' => 'str',
'value' => $report->message,
'caption' => 'Reason',
];
if ($noZapped) {
$cur['fields']['zap' . $report->id] = [
'type' => 'btn',
@ -123,6 +127,7 @@ class Reports extends Admin
'link' => $report->linkZap,
];
}
$form['sets'][$report->id] = $cur;
}

View file

@ -16,6 +16,8 @@ use function \ForkBB\{__, num};
class Statistics extends Admin
{
const CACHE_KEY = 'phpinfoCSS';
/**
* phpinfo
*/
@ -53,7 +55,7 @@ class Statistics extends Admin
$matches[1]
);
$this->c->Cache->set('phpinfoCSS', $style);
$this->c->Cache->set(self::CACHE_KEY, $style);
$this->pageHeader('phpinfoStyle', 'link', 0, [
'rel' => 'stylesheet',
'type' => 'text/css',
@ -81,7 +83,7 @@ class Statistics extends Admin
$this->c->DEBUG = 0;
$this->nameTpl = 'layouts/plain';
$this->plainText = $this->c->Cache->get('phpinfoCSS', '');
$this->plainText = $this->c->Cache->get(self::CACHE_KEY, '');
$this->header('Content-type', 'text/css; charset=utf-8');

View file

@ -31,13 +31,12 @@ class Update extends Admin
const JSON_OPTIONS = \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR;
const CONFIG_FILE = 'main.php';
protected $configFile;
protected string $configFile;
/**
* Флаг проверки пароля
* @var bool
*/
protected $okPass;
protected bool $okPass;
public function __construct(Container $container)
{
@ -204,6 +203,7 @@ class Update extends Admin
],
'PRIMARY KEY' => ['id'],
];
if (
null === $e
&& false === $this->c->DB->createTable($testTable, $schema)

View file

@ -38,6 +38,7 @@ abstract class Users extends Admin
{
if (\is_array($data)) {
unset($data['token']);
$data = \base64_encode(\json_encode($data));
$hash = $this->c->Secury->hash($data);
@ -92,6 +93,7 @@ abstract class Users extends Admin
$userList = $this->c->users->loadByIds($selected);
$result = [];
foreach ($userList as $user) {
if (! $user instanceof User) {
continue;
@ -104,34 +106,41 @@ abstract class Users extends Admin
return false;
}
if (! $this->c->userRules->canBanUser($user)) {
$this->fIswev = ['v', ['You are not allowed to ban the %s', $user->username]];
if ($user->isAdmMod) {
$this->fIswev = ['i', 'No ban admins message'];
}
return false;
}
break;
case self::ACTION_DEL:
if (! $this->c->userRules->canDeleteUser($user)) {
$this->fIswev = ['v', ['You are not allowed to delete the %s', $user->username]];
if ($user->isAdmMod) {
$this->fIswev = ['i', 'No delete admins message'];
}
return false;
}
break;
case self::ACTION_CHG:
if (! $this->c->userRules->canChangeGroup($user, $profile)) {
$this->fIswev = ['v', ['You are not allowed to change group for %s', $user->username]];
if ($user->isAdmin) {
$this->fIswev = ['i', 'No move admins message'];
}
return false;
}
break;
default:
$this->fIswev = ['v', 'Action not available'];
@ -140,6 +149,7 @@ abstract class Users extends Admin
}
$result[] = $user->id;
if ($user->id === $this->user->id) {
$this->fIswev = ['i', 'You are trying to change your own group'];
}

View file

@ -25,9 +25,11 @@ class Action extends Users
protected function nameList(array $users): array
{
$result = [];
foreach ($users as $user) {
$result[] = $user->username;
}
\sort($result, \SORT_STRING | \SORT_FLAG_CASE);
return $result;
@ -42,12 +44,14 @@ class Action extends Users
if (! $this->c->Csrf->verify($args['token'], 'AdminUsersAction', $args)) {
return $this->c->Message->message($this->c->Csrf->getError());
}
$profile = true;
} else {
$profile = false;
}
$error = false;
switch ($args['action']) {
/*
case self::ACTION_BAN:
@ -60,6 +64,7 @@ class Action extends Users
if (! $this->c->userRules->deleteUsers) {
$error = true;
}
break;
case self::ACTION_CHG:
if (
@ -73,6 +78,7 @@ class Action extends Users
) {
$error = true;
}
break;
default:
$error = true;
@ -83,6 +89,7 @@ class Action extends Users
}
$ids = $this->checkSelected(\explode('-', $args['ids']), $args['action'], $profile);
if (false === $ids) {
$message = $this->c->Message->message('Action not available');
$message->fIswev = $this->fIswev; // тут идет дополнение, а не замена
@ -91,6 +98,7 @@ class Action extends Users
}
$this->userList = $this->c->users->loadByIds($ids);
switch ($args['action']) {
/*
case self::ACTION_BAN:
@ -212,10 +220,13 @@ class Action extends Users
protected function groupListForChange(bool $profile): array
{
$list = [];
foreach ($this->c->groups->getList() as $id => $group) {
$list[$id] = $group->g_title;
}
unset($list[FORK_GROUP_GUEST]);
if (! $profile) {
unset($list[FORK_GROUP_ADMIN]);
} elseif (! $this->user->isAdmin) {
@ -306,11 +317,8 @@ class Action extends Users
/**
* Проверяет пароль на совпадение с текущим пользователем
*/
public function vCheckPassword(
Validator $v,
#[SensitiveParameter]
string $password
): string {
public function vCheckPassword(Validator $v, #[SensitiveParameter] string $password): string
{
if (! \password_verify($password, $this->user->password)) {
$v->addError('Invalid passphrase');
}

View file

@ -25,8 +25,10 @@ class Promote extends Users
}
$user = $this->c->users->load($args['uid']);
if (0 < $user->g_promote_next_group * $user->g_promote_min_posts) {
$user->group_id = $user->g_promote_next_group;
$this->c->users->update($user);
}

View file

@ -42,6 +42,7 @@ class Result extends Users
}
$number = \count($idsN);
if (0 == $number) {
$view = $this->c->AdminUsers;
$view->fIswev = ['i', 'No users found'];
@ -122,6 +123,7 @@ class Result extends Users
if (\is_int($cur)) {
$ids[] = $cur;
}
$userList[$cur] = $cur;
}

View file

@ -80,6 +80,7 @@ class Stat extends Users
];
\array_unshift($stat, ['last_used' => null, 'used_times' => null]);
$flag = false;
foreach ($stat as $ip => $data) {
@ -133,6 +134,7 @@ class Stat extends Users
];
++$number;
$flag = true;
}

View file

@ -54,6 +54,7 @@ class Auth extends Page
$this->c->Lang->load('auth');
$v = null;
if ('POST' === $method) {
$v = $this->c->Validator->reset()
->addValidators([
@ -180,11 +181,8 @@ class Auth extends Page
/**
* Проверка пользователя по базе
*/
public function vLoginCheck(
Validator $v,
#[SensitiveParameter]
string $password
): string {
public function vLoginCheck(Validator $v, #[SensitiveParameter] string $password ): string
{
if (empty($v->getErrors())) {
$this->userAfterLogin = $this->c->users->loadByName($v->username);

View file

@ -211,12 +211,14 @@ class Edit extends Page
if ($calcTopic) {
$topic->calcStat();
}
$this->c->topics->update($topic);
// обновление раздела
if ($calcForum) {
$topic->parent->calcStat();
}
$this->c->forums->update($topic->parent);
// антифлуд

View file

@ -17,11 +17,7 @@ use function \ForkBB\__;
class Email extends Page
{
/**
* Получатель
* @var User
*/
protected $curUser;
protected User $curUser;
/**
* Подготовка данных для шаблона
@ -57,6 +53,7 @@ class Email extends Page
$floodSize = \time() - (int) $this->user->last_email_sent;
$floodSize = $floodSize < $this->user->g_email_flood ? $this->user->g_email_flood - $floodSize : 0;
if ($floodSize > 0) {
$this->fIswev = ['e', ['Flood message', $floodSize]];
}

View file

@ -119,6 +119,7 @@ class Feed extends Page
}
$items = $this->c->posts->feed($forum);
if (! empty($items)) {
foreach ($items as $cur) {
$fName = $this->c->forums->get($cur['fid'])->forum_name;

View file

@ -25,6 +25,7 @@ class Forum extends Page
$this->c->Lang->load('subforums');
$forum = $this->c->forums->loadTree($args['id']);
if (! $forum instanceof ForumModel) {
return $this->c->Message->message('Bad request');
}
@ -35,6 +36,7 @@ class Forum extends Page
}
$forum->page = $args['page'] ?? 1;
if (! $forum->hasPage()) {
return $this->c->Message->message('Not Found', true, 404);
}
@ -67,6 +69,7 @@ class Forum extends Page
if ($this->c->config->i_feed_type > 0) {
$feedType = 2 === $this->c->config->i_feed_type ? 'atom' : 'rss';
$this->pageHeader('feed', 'link', 0, [
'rel' => 'alternate',
'type' => "application/{$feedType}+xml",

View file

@ -70,6 +70,7 @@ class Index extends Page
if ($this->c->config->i_feed_type > 0) {
$feedType = 2 === $this->c->config->i_feed_type ? 'atom' : 'rss';
$this->pageHeader('feed', 'link', 0, [
'rel' => 'alternate',
'type' => "application/{$feedType}+xml",

View file

@ -23,6 +23,7 @@ class Misc extends Page
public function markread(array $args): Page
{
$forum = $this->c->forums->loadTree($args['id']);
if (! $forum instanceof Forum) {
return $this->c->Message->message('Bad request');
}
@ -50,6 +51,7 @@ class Misc extends Page
}
$forum = $this->c->forums->get($args['fid']);
if (! $forum instanceof Forum) {
return $this->c->Message->message('Bad request');
}
@ -83,6 +85,7 @@ class Misc extends Page
}
$topic = $this->c->topics->load($args['tid']);
if (! $topic instanceof Topic) {
return $this->c->Message->message('Bad request');
}

View file

@ -28,9 +28,8 @@ class Moderate extends Page
/**
* Список действий
* @var array
*/
protected $actions = [
protected array $actions = [
'open' => self::INFORUM + self::INTOPIC + self::TOTOPIC,
'close' => self::INFORUM + self::INTOPIC + self::TOTOPIC,
'delete' => self::INFORUM + self::INTOPIC + self::IFTOTPC,
@ -63,7 +62,8 @@ class Moderate extends Page
$cid = null;
$options = [];
$idxs = [];
$root = $this->c->forums->get(0);
$root = $this->c->forums->get(0);
if ($root instanceof Forum) {
foreach ($this->c->forums->depthList($root, -1) as $f) {
if ($cid !== $f->cat_id) {
@ -87,6 +87,7 @@ class Moderate extends Page
}
}
}
$this->listOfIndexes = $idxs;
$this->listForOptions = $options;
}
@ -99,6 +100,7 @@ class Moderate extends Page
if (empty($v->getErrors())) {
$type = $v->topic ? self::INTOPIC : self::INFORUM;
$sum = 0;
foreach ($this->actions as $key => $val) {
if (isset($v->{$key})) {
$action = $key;
@ -197,6 +199,7 @@ class Moderate extends Page
}
$this->curForum = $this->c->forums->loadTree($v->forum);
if (! $this->curForum instanceof Forum) {
return $this->c->Message->message('Bad request');
} elseif (
@ -210,6 +213,7 @@ class Moderate extends Page
if ($v->topic) {
$this->curTopic = $this->c->topics->load($v->topic);
if (
! $this->curTopic instanceof Topic
|| $this->curTopic->parent !== $this->curForum
@ -221,6 +225,7 @@ class Moderate extends Page
$curType = $this->actions[$v->action];
$ids = $v->ids;
$firstId = $this->curTopic->first_post_id;
if (self::TOTOPIC & $curType) {
$objects = [$this->curTopic];
} elseif (self::IFTOTPC & $curType) {
@ -231,8 +236,10 @@ class Moderate extends Page
$objects = [$this->curTopic];
}
}
if (null === $objects) {
$objects = $this->c->posts->loadByIds(\array_diff($ids, [$firstId]), false);
foreach ($objects as $post) {
if (
! $post instanceof Post
@ -241,6 +248,7 @@ class Moderate extends Page
return $this->c->Message->message('Bad request');
}
}
$this->processAsPosts = true;
}
@ -254,6 +262,7 @@ class Moderate extends Page
);
} else {
$objects = $this->c->topics->loadByIds($v->ids, false);
foreach ($objects as $topic) {
if (
! $topic instanceof Topic
@ -432,6 +441,7 @@ class Moderate extends Page
if ($topic->moved_to) {
return $this->c->Message->message('Topic links cannot be merged');
}
if (
! $this->firstTopic instanceof Topic
|| $topic->first_post_id < $this->firstTopic->first_post_id
@ -583,6 +593,7 @@ class Moderate extends Page
}
$headers = [];
foreach ($objects as $object) {
if ($object instanceof Topic) {
$headers[] = __(['Topic «%s»', $object->name]);

View file

@ -13,20 +13,14 @@ namespace ForkBB\Models\Pages\PM;
use ForkBB\Core\Container;
use ForkBB\Models\Page;
use ForkBB\Models\PM\Cnst;
use ForkBB\Models\PM\PM;
use ForkBB\Models\User\User;
use function \ForkBB\__;
abstract class AbstractPM extends Page
{
/**
* @var array
*/
protected $pmCrumbs = [];
/**
* @var ForkBB\Models\PM\Manager
*/
protected $pms;
protected array $pmCrumbs = [];
protected PM $pms;
public function __construct(Container $container)
{
@ -137,9 +131,11 @@ abstract class AbstractPM extends Page
case Cnst::ACTION_EDIT:
case Cnst::ACTION_DELETE:
$viewArea = true;
break;
case Cnst::ACTION_BLOCK:
case Cnst::ACTION_CONFIG:
break;
default:
$crumbs[] = [null, ['%s', 'unknown']];

View file

@ -35,17 +35,17 @@ class Poll extends Page
$this->c->Lang->load('poll');
$v = $this->c->Validator->reset()
->addValidators([
])->addRules([
'token' => 'token:Poll',
'poll_vote.*.*' => 'required|integer',
'vote' => 'required|string',
])->addAliases([
])->addArguments([
'token' => $args,
])->addMessages([
'poll_vote.*.*' => 'The poll structure is broken',
]);
->addValidators([
])->addRules([
'token' => 'token:Poll',
'poll_vote.*.*' => 'required|integer',
'vote' => 'required|string',
])->addAliases([
])->addArguments([
'token' => $args,
])->addMessages([
'poll_vote.*.*' => 'The poll structure is broken',
]);
if (! $v->validation($_POST)) {
$message = $this->c->Message;

View file

@ -301,6 +301,7 @@ class Post extends Page
$this->user->group_id = $this->user->g_promote_next_group;
}
}
if ($createTopic) {
$this->user->num_topics = $this->user->num_topics + 1;
}

View file

@ -269,6 +269,7 @@ trait PostFormTrait
if (empty($section['fields'])) {
continue;
}
foreach ($section['fields'] as $key => &$cur) {
if (
$key === $field

View file

@ -128,6 +128,7 @@ trait PostValidatorTrait
$ruleStickTopic = 'absent';
$ruleStickFP = 'absent';
}
if (
! $first
&& ! $edit
@ -136,6 +137,7 @@ trait PostValidatorTrait
} else {
$ruleMergePost = 'absent';
}
if (
$edit
&& ! $model->user->isGuest
@ -145,6 +147,7 @@ trait PostValidatorTrait
} else {
$ruleEditPost = 'absent';
}
$executive = true;
} else {
$ruleStickTopic = 'absent';

View file

@ -51,11 +51,8 @@ abstract class Profile extends Page
/**
* Проверяет пароль на совпадение с текущим пользователем
*/
public function vCheckPassword(
Validator $v,
#[SensitiveParameter]
string $password
): string {
public function vCheckPassword(Validator $v, #[SensitiveParameter] string $password): string
{
if (! \password_verify($password, $this->user->password)) {
$v->addError('Invalid passphrase');
}
@ -91,6 +88,7 @@ abstract class Profile extends Page
__('Change user group'),
];
}
if ($this->rules->banUser) {
$id = $this->c->bans->banFromName($this->curUser->username);
@ -118,6 +116,7 @@ abstract class Profile extends Page
];
}
}
if ($this->rules->deleteUser) {
$btns['delete-user'] = [
$this->c->Router->link(
@ -130,6 +129,7 @@ abstract class Profile extends Page
__('Delete user'),
];
}
if (
'edit' != $type
&& $this->rules->editProfile
@ -144,12 +144,14 @@ abstract class Profile extends Page
__('Edit '),
];
}
if ('view' != $type) {
$btns['view-profile'] = [
$this->curUser->link,
__('View '),
];
}
if (
'config' != $type
&& $this->rules->editConfig

View file

@ -24,9 +24,8 @@ class Edit extends Profile
{
/**
* Паттерн для доступных к загрузке типов файлов
* @var string
*/
protected $accept = 'image/*';
protected string $accept = 'image/*';
/**
* Подготавливает данные для шаблона редактирования профиля

View file

@ -83,9 +83,11 @@ class Report extends Page
'headers' => false,
]);
}
break;
default:
$this->c->reports->insert($report);
break;
}

View file

@ -28,6 +28,7 @@ class Search extends Page
$options = [];
$idxs = [];
$root = $this->c->forums->get(0);
if ($root instanceof Forum) {
foreach ($this->c->forums->depthList($root, -1) as $f) {
if ($cid !== $f->cat_id) {
@ -45,6 +46,7 @@ class Search extends Page
}
}
}
$this->listOfIndexes = $idxs;
$this->listForOptions = $options;
}
@ -414,6 +416,7 @@ class Search extends Page
$forum = $args['forum'] ?? 0;
$forum = $this->c->forums->get($forum);
if (! $forum instanceof Forum) {
return $this->c->Message->message('Bad request');
}
@ -430,6 +433,7 @@ class Search extends Page
'unanswered_topics' => 'unanswered',
'new' => 'new',
];
switch ($action) {
case 'search':
if (1 === $model->showAs) {
@ -438,13 +442,16 @@ class Search extends Page
$list = $model->actionP($action, $forum);
$asTopicsList = false;
}
if ('*' === $args['author']) {
$model->name = ['Search query: %s', $args['keywords']];
} else {
$model->name = ['Search query: %1$s and Author: %2$s', $args['keywords'], $args['author']];
}
$model->linkMarker = $advanced ? 'SearchAdvanced' : 'Search';
$model->linkArgs = $args;
break;
case 'new':
case 'topics_with_your_posts':
@ -456,16 +463,20 @@ class Search extends Page
if (isset($uid)) {
break;
}
$uid = $this->user->id;
$list = $model->actionT($action, $forum, $uid);
$model->name = __('Quick search ' . $action);
$model->linkMarker = 'SearchAction';
if ($forum->id) {
$model->linkArgs = ['action' => $action, 'forum' => $forum->id];
} else {
$model->linkArgs = ['action' => $action];
}
$this->fSubIndex = $subIndex[$action];
break;
case 'posts':
$asTopicsList = false;
@ -475,13 +486,16 @@ class Search extends Page
if (! isset($uid)) {
break;
}
$user = $this->c->users->load($uid);
if (
! $user instanceof User
|| $user->isGuest
) {
break;
}
if ('forums_subscriptions' == $action) {
$list = $model->actionF($action, $forum, $user->id);
} elseif ($asTopicsList) {
@ -489,8 +503,10 @@ class Search extends Page
} else {
$list = $model->actionP($action, $forum, $user->id);
}
$model->name = ['Quick search user ' . $action, $user->username];
$model->linkMarker = 'SearchAction';
if ($forum->id) {
$model->linkArgs = ['action' => $action, 'uid' => $user->id, 'forum' => $forum->id];
} else {

View file

@ -67,12 +67,15 @@ class Topic extends Page
switch ($type) {
case 'new':
$pid = $topic->firstNew;
break;
case 'unread':
$pid = $topic->firstUnread;
break;
case 'last':
$pid = $topic->last_post_id;
break;
default:
return $this->c->Message->message('Bad request');
@ -108,9 +111,11 @@ class Topic extends Page
switch ($type) {
case 'topic':
$topic->page = $args['page'] ?? 1;
break;
case 'post':
$topic->calcPage($args['id']);
break;
default:
return $this->go($type, $topic);

View file

@ -54,6 +54,7 @@ class Userlist extends Page
]);
$error = true;
if ($v->validation('POST' === $method ? $_POST : $args)) {
$count = (int) (null === $v->sort)
+ (int) (null === $v->dir)
@ -67,19 +68,23 @@ class Userlist extends Page
$error = false;
}
}
if ($error) {
return $this->c->Message->message('Bad request');
}
if ('POST' === $method) {
return $this->c->Redirect->page('Userlist', $v->getData());
}
$filters = [];
if (\is_numeric($v->group)) {
$filters['group_id'] = ['=', $v->group];
} else {
$filters['group_id'] = ['!=', 0];
}
if (null !== $v->name) {
$filters['username'] = ['LIKE', $v->name];
@ -108,7 +113,7 @@ class Userlist extends Page
$this->userList = $this->c->users->loadByIds($ids);
$links = [];
$vars = ['page' => $page];
$vars = ['page' => $page];
if (4 === $count) {
$vars['group'] = 'all';
@ -194,6 +199,7 @@ class Userlist extends Page
} else {
$form['hidden']['name'] = '*';
}
$fields['group'] = [
'class' => ['w4'],
'type' => 'select',

View file

@ -273,6 +273,7 @@ class Poll extends DataModel
foreach (\array_keys($this->question) as $q) {
if ($this->type[$q] > 1) {
$count = \count($vote[$q]);
if (0 == $count) {
return __(['No vote on question %s', $q]);
} elseif ($count > $this->type[$q]) {

View file

@ -42,6 +42,7 @@ class Feed extends Action
} elseif ($model instanceof Forum) {
$ids = \array_keys($model->descendants);
if ($model->id) {
$ids[] = $model->id;
}

View file

@ -107,11 +107,13 @@ class Load extends Action
if ($withTopics) {
$this->c->topics->loadByIds($topicIds, true);
foreach ($result as &$post) {
if (! $post->parent instanceof Topic) {
$post = null;
}
}
unset($post);
} else {
foreach ($topicIds as $id) {

View file

@ -31,6 +31,7 @@ class Move extends Action
if ($useFrom) {
$post->message = "[from]{$post->parent->subject}[/from]\n" . $post->message;
}
$post->topic_id = $toTopic->id;
$this->c->posts->update($post);
}
@ -39,6 +40,7 @@ class Move extends Action
//???? перерасчет количества тем у пользователей? или нет?
$forums = [];
foreach ($topics as $topic) {
$forums[$topic->forum_id] = $topic->parent;

View file

@ -115,7 +115,7 @@ class Post extends DataModel
return false;
} elseif ($this->c->user->isModerator($this)) {
return true;
} elseif ('1' == $this->parent->closed) {
} elseif (0 !== $this->parent->closed) {
return false;
}
@ -131,8 +131,8 @@ class Post extends DataModel
)
)
&& (
'0' == $this->c->user->g_deledit_interval
|| '1' == $this->edit_post
0 === $this->c->user->g_deledit_interval
|| 1 === $this->edit_post
|| \time() - $this->posted < $this->c->user->g_deledit_interval
);
}
@ -164,15 +164,15 @@ class Post extends DataModel
return false;
} elseif ($this->c->user->isModerator($this)) {
return true;
} elseif ('1' == $this->parent->closed) {
} elseif (0 !== $this->parent->closed) {
return false;
}
return $this->user->id === $this->c->user->id
&& 1 === $this->c->user->g_edit_posts
&& (
'0' == $this->c->user->g_deledit_interval
|| '1' == $this->edit_post
0 === $this->c->user->g_deledit_interval
|| 1 === $this->edit_post
|| \time() - $this->posted < $this->c->user->g_deledit_interval
|| (
$this->user->id === $this->editor_id

View file

@ -24,23 +24,30 @@ class Save extends Action
if ($post->id < 1) {
throw new RuntimeException('The model does not have ID');
}
$modified = $post->getModified();
if (empty($modified)) {
return $post;
}
$values = $post->getAttrs();
$fileds = $this->c->dbMap->posts;
$set = $vars = [];
foreach ($modified as $name) {
if (! isset($fileds[$name])) {
continue;
}
$vars[] = $values[$name];
$set[] = $name . '=?' . $fileds[$name];
}
if (empty($set)) {
return $post;
}
$vars[] = $post->id;
$set = \implode(', ', $set);
@ -62,20 +69,25 @@ class Save extends Action
if (null !== $post->id) {
throw new RuntimeException('The model has ID');
}
$attrs = $post->getAttrs();
$fileds = $this->c->dbMap->posts;
$set = $set2 = $vars = [];
foreach ($attrs as $key => $value) {
if (! isset($fileds[$key])) {
continue;
}
$vars[] = $value;
$set[] = $key;
$set2[] = '?' . $fileds[$key];
}
if (empty($set)) {
throw new RuntimeException('The model is empty');
}
$set = \implode(', ', $set);
$set2 = \implode(', ', $set2);
$query = "INSERT INTO ::posts ({$set})

View file

@ -59,6 +59,7 @@ class View extends Action
if (isset($warnings[$post->id])) {
$post->__warnings = $warnings[$post->id];
}
$userIds[$post->poster_id] = $post->poster_id;
}
}
@ -67,6 +68,7 @@ class View extends Action
$offset = ($arg->page - 1) * $this->c->user->disp_posts;
$timeMax = 0;
if ($review) {
$postCount = $arg->num_replies + 2;
$sign = -1;
@ -89,22 +91,28 @@ class View extends Action
if (empty($post->id)) {
continue;
}
$post->__postNumber = 1;
} else {
$postCount += $sign;
if (empty($post->id)) {
continue;
}
$post->__postNumber = $offset + $postCount;
}
}
$arg->timeMax = $timeMax;
} else {
foreach ($result as $post) {
++$postCount;
if (empty($post->id)) {
continue;
}
$post->__postNumber = $offset + $postCount; //????
}
}

View file

@ -17,6 +17,8 @@ use RuntimeException;
class Reports extends Manager
{
const CACHE_KEY = 'report';
/**
* Ключ модели для контейнера
*/
@ -51,6 +53,7 @@ class Reports extends Manager
public function loadList(bool $noZapped = true): array
{
$result = [];
foreach ($this->Load->loadList($noZapped) as $report) {
if ($this->isset($report->id)) {
$result[] = $this->get($report->id);
@ -88,7 +91,7 @@ class Reports extends Manager
*/
public function lastId(): int
{
$last = $this->c->Cache->get('report');
$last = $this->c->Cache->get(self::CACHE_KEY);
if (null === $last) {
$query = 'SELECT MAX(r.id)
@ -96,7 +99,7 @@ class Reports extends Manager
$last = (int) $this->c->DB->query($query)->fetchColumn();
if (true !== $this->c->Cache->set('report', $last)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $last)) {
throw new RuntimeException('Unable to write value to cache - report');
}
}

View file

@ -24,23 +24,30 @@ class Save extends Action
if ($report->id < 1) {
throw new RuntimeException('The model does not have ID');
}
$modified = $report->getModified();
if (empty($modified)) {
return $report;
}
$values = $report->getAttrs();
$fileds = $this->c->dbMap->reports;
$set = $vars = [];
foreach ($modified as $name) {
if (! isset($fileds[$name])) {
continue;
}
$vars[] = $values[$name];
$set[] = $name . '=?' . $fileds[$name];
}
if (empty($set)) {
return $report;
}
$vars[] = $report->id;
$set = \implode(', ', $set);
@ -68,17 +75,21 @@ class Save extends Action
$attrs = $report->getAttrs();
$fileds = $this->c->dbMap->reports;
$set = $set2 = $vars = [];
foreach ($attrs as $key => $value) {
if (! isset($fileds[$key])) {
continue;
}
$vars[] = $value;
$set[] = $key;
$set2[] = '?' . $fileds[$key];
}
if (empty($set)) {
throw new RuntimeException('The model is empty');
}
$set = \implode(', ', $set);
$set2 = \implode(', ', $set2);
$query = "INSERT INTO ::reports ({$set})

View file

@ -32,6 +32,7 @@ class ActionF extends Method
}
$list = [];
switch ($action) {
case 'forums_subscriptions':
if (0 !== $root->id) {

View file

@ -32,9 +32,11 @@ class ActionP extends Method
}
$query = null;
switch ($action) {
case 'search':
$list = $this->model->queryIds;
break;
case 'posts':
$query = 'SELECT p.id
@ -42,6 +44,7 @@ class ActionP extends Method
INNER JOIN ::topics AS t ON t.id=p.topic_id
WHERE t.forum_id IN (?ai:forums) AND t.moved_to=0 AND p.poster_id=?i:uid
ORDER BY p.posted DESC';
break;
default:
throw new InvalidArgumentException('Unknown action: ' . $action);

View file

@ -32,9 +32,11 @@ class ActionT extends Method
}
$query = null;
switch ($action) {
case 'search':
$list = $this->model->queryIds;
break;
case 'latest_active_topics':
$query = 'SELECT t.id
@ -42,12 +44,14 @@ class ActionT extends Method
WHERE t.forum_id IN (?ai:forums) AND t.moved_to=0
ORDER BY t.last_post DESC
LIMIT 1000';
break;
case 'unanswered_topics':
$query = 'SELECT t.id
FROM ::topics AS t
WHERE t.forum_id IN (?ai:forums) AND t.moved_to=0 AND t.num_replies=0
ORDER BY t.last_post DESC';
break;
case 'topics_with_your_posts':
$query = 'SELECT t.id
@ -56,6 +60,7 @@ class ActionT extends Method
WHERE t.forum_id IN (?ai:forums) AND t.moved_to=0 AND p.poster_id=?i:uid
GROUP BY t.id
ORDER BY t.last_post DESC';
break;
case 'topics':
$query = 'SELECT t.id
@ -63,6 +68,7 @@ class ActionT extends Method
INNER JOIN ::posts AS p ON t.first_post_id=p.id
WHERE t.forum_id IN (?ai:forums) AND t.moved_to=0 AND p.poster_id=?i:uid
ORDER BY t.first_post_id DESC'; // t.last_post
break;
case 'new':
$query = 'SELECT t.id
@ -75,6 +81,7 @@ class ActionT extends Method
AND (mot.mt_last_visit IS NULL OR t.last_post>mot.mt_last_visit)
AND (mof.mf_mark_all_read IS NULL OR t.last_post>mof.mf_mark_all_read)
ORDER BY t.last_post DESC';
break;
case 'topics_subscriptions':
if (0 !== $root->id) {
@ -92,6 +99,7 @@ class ActionT extends Method
$list = $subscrInfo[$subscr::TOPICS_DATA] ?? [];
\arsort($list, \SORT_NUMERIC); // ???? или по последнему сообщению делать?
break;
default:
throw new InvalidArgumentException('Unknown action: ' . $action);

View file

@ -80,11 +80,13 @@ class Execute extends Method
}
$ids = $this->exec($this->model->queryWords, $queryVars);
if (1 === $v->sort_dir) {
\asort($ids, $this->sortType);
} else {
\arsort($ids, $this->sortType);
}
$ids = \array_keys($ids);
$data = [
@ -123,6 +125,7 @@ class Execute extends Method
|| 'NOT' === $word
) {
$type = $word;
continue;
}
@ -167,6 +170,7 @@ class Execute extends Method
} else {
$this->stmtCJK->execute($vars);
}
$this->words[$word] = $list = $this->stmtCJK->fetchAll(PDO::FETCH_KEY_PAIR);
} else {
if (null === $this->stmtIdx) {
@ -175,6 +179,7 @@ class Execute extends Method
} else {
$this->stmtIdx->execute($vars);
}
$this->words[$word] = $list = $this->stmtIdx->fetchAll(PDO::FETCH_KEY_PAIR);
}
}
@ -235,19 +240,23 @@ class Execute extends Method
$whereIdx[] = 'sm.subject_match=0';
$whereCJK[] = "p.message {$like} ?s:word";
$usePCJK = true;
if (isset($vars[':author'])) {
$whereCJK[] = "p.poster {$like} ?s:author ESCAPE '#'";
}
break;
case 2:
$whereIdx[] = 'sm.subject_match=1';
$whereCJK[] = "t.subject {$like} ?s:word";
$useTCJK = true;
if (isset($vars[':author'])) {
$whereCJK[] = "t.poster {$like} ?s:author ESCAPE '#'";
}
// при поиске в заголовках результат только в виде списка тем
$this->model->showAs = 1;
break;
default:
if (isset($vars[':author'])) {
@ -255,8 +264,10 @@ class Execute extends Method
} else {
$whereCJK[] = "(p.message {$like} ?s:word OR t.subject {$like} ?s:word)";
}
$usePCJK = true;
$useTCJK = true;
break;
}
@ -284,7 +295,9 @@ class Execute extends Method
$usePIdx = true;
$usePCJK = true;
}
$this->sortType = \SORT_STRING;
break;
case 2:
$sortIdx = 't.subject';
@ -292,6 +305,7 @@ class Execute extends Method
$useTIdx = true;
$useTCJK = true;
$this->sortType = \SORT_STRING;
break;
case 3:
$sortIdx = 't.forum_id';
@ -299,6 +313,7 @@ class Execute extends Method
$useTIdx = true;
$useTCJK = true;
$this->sortType = \SORT_NUMERIC;
break;
default:
if (1 === $this->model->showAs) {
@ -311,7 +326,9 @@ class Execute extends Method
$sortCJK = 'p.id';
$usePCJK = true;
}
$this->sortType = \SORT_NUMERIC;
break;
}

View file

@ -40,6 +40,7 @@ class Index extends Method
$mesCurWords = [];
$subCurWords = [];
while ($row = $stmt->fetch()) {
if ($row['subject_match']) {
$subCurWords[$row['word']] = $row['id'];
@ -50,6 +51,7 @@ class Index extends Method
}
$words = [];
if ('edit' === $mode) {
$words['add']['p'] = \array_diff($mesWords, \array_keys($mesCurWords));
$words['add']['s'] = \array_diff($subWords, \array_keys($subCurWords));
@ -87,6 +89,7 @@ class Index extends Method
$query = 'INSERT INTO ::search_words (word)
VALUES(?s:word)';
$stmt = null;
foreach ($newWords as $word) {
if (null === $stmt) {
$stmt = $this->c->DB->prepare($query, [':word' => $word]);

View file

@ -55,10 +55,13 @@ class Prepare extends Method
} else {
$words[] = ['type' => 'CJK', 'word' => $subQuery];
}
$keyword = false;
++$count;
}
$quotes = false;
continue;
}
@ -83,6 +86,7 @@ class Prepare extends Method
case '-':
case '!':
$key = $key ?: 'NOT';
if (! $keyword) {
$keyword = true;
} elseif (empty($words)) {
@ -90,13 +94,16 @@ class Prepare extends Method
} else {
$error = 'Logical operators follow one after another: \'%s\'';
}
$words[] = $key;
break;
case '(':
$stack[] = [$words, $keyword, $count];
$words = [];
$keyword = true;
$count = 0;
break;
case ')':
if (! $count) {
@ -109,21 +116,26 @@ class Prepare extends Method
} else {
$temp = $words;
list($words, $keyword, $count) = \array_pop($stack);
if (! $keyword) {
$words[] = 'AND';
}
$words[] = $temp;
$keyword = false;
++$count;
}
break;
default:
$cur = \mb_strtolower($cur, 'UTF-8');
$cur = $this->model->cleanText($cur); //????
$temp = [];
$countT = 0;
foreach (\explode(' ', $cur) as $word) {
$word = $this->model->word($word);
if (null === $word) {
continue;
}
@ -137,8 +149,10 @@ class Prepare extends Method
} else {
$temp[] = $word;
}
++$countT;
}
if ($countT) {
if (! $keyword) {
$words[] = 'AND';
@ -153,8 +167,10 @@ class Prepare extends Method
$words[] = $temp;
++$count;
}
$keyword = false;
}
break;
}
}
@ -183,6 +199,7 @@ class Prepare extends Method
{
$space = '';
$result = '';
foreach ($words as $word) {
if (
isset($word['type'])
@ -192,6 +209,7 @@ class Prepare extends Method
} elseif (\is_array($word)) {
$word = '(' . $this->queryText($word) . ')';
}
$result .= $space . $word;
$space = ' ';
}

View file

@ -15,6 +15,8 @@ use RuntimeException;
class SmileyList extends Model
{
const CACHE_KEY = 'smilies';
/**
* Ключ модели для контейнера
*/
@ -26,12 +28,12 @@ class SmileyList extends Model
*/
public function init(): SmileyList
{
$list = $this->c->Cache->get('smilies');
$list = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($list)) {
$list = $this->load();
if (true !== $this->c->Cache->set('smilies', $list)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $list)) {
throw new RuntimeException('Unable to write value to cache - smilies');
}
}
@ -46,7 +48,7 @@ class SmileyList extends Model
*/
public function reset(): SmileyList
{
if (true !== $this->c->Cache->delete('smilies')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - smilies');
}

View file

@ -16,6 +16,8 @@ use RuntimeException;
class Stats extends Model
{
const CACHE_KEY = 'stats';
/**
* Ключ модели для контейнера
*/
@ -26,12 +28,12 @@ class Stats extends Model
*/
public function init(): Stats
{
$list = $this->c->Cache->get('stats');
$list = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($list)) {
$list = $this->c->users->stats();
if (true !== $this->c->Cache->set('stats', $list)) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, $list)) {
throw new RuntimeException('Unable to write value to cache - stats');
}
}
@ -52,7 +54,7 @@ class Stats extends Model
*/
public function reset(): Stats
{
if (true !== $this->c->Cache->delete('stats')) {
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - stats');
}

View file

@ -15,6 +15,8 @@ use RuntimeException;
class StopwordList extends Model
{
const CACHE_KEY = 'stopwords';
/**
* Ключ модели для контейнера
*/
@ -25,7 +27,8 @@ class StopwordList extends Model
*/
public function init(): StopwordList
{
$data = $this->c->Cache->get('stopwords');
$data = $this->c->Cache->get(self::CACHE_KEY);
if (
isset($data['id'], $data['stopwords'])
&& $data['id'] === $this->generateId()
@ -48,6 +51,7 @@ class StopwordList extends Model
}
$files = \glob($this->c->DIR_LANG . '/*/stopwords.txt');
if (false === $files) {
return 'cache_id_error';
}
@ -77,6 +81,7 @@ class StopwordList extends Model
}
$stopwords = [];
foreach ($this->files as $file) {
$stopwords = \array_merge($stopwords, \file($file));
}
@ -86,7 +91,7 @@ class StopwordList extends Model
$stopwords = \array_filter($stopwords);
$stopwords = \array_flip($stopwords);
if (true !== $this->c->Cache->set('stopwords', ['id' => $id, 'stopwords' => $stopwords])) {
if (true !== $this->c->Cache->set(self::CACHE_KEY, ['id' => $id, 'stopwords' => $stopwords])) {
throw new RuntimeException('Unable to write value to cache - stopwords');
}

View file

@ -21,6 +21,7 @@ class Access extends Action
public function access(bool $open, Topic ...$topics): void
{
$ids = [];
foreach ($topics as $topic) {
$ids[] = $topic->id;
$topic->__closed = $open ? 0 : 1;

View file

@ -102,6 +102,7 @@ class Load extends Action
$stmt = $this->c->DB->query($query, $vars);
$result = [];
while ($row = $stmt->fetch()) {
$topic = $this->manager->create($row);

View file

@ -24,23 +24,30 @@ class Save extends Action
if ($topic->id < 1) {
throw new RuntimeException('The model does not have ID');
}
$modified = $topic->getModified();
if (empty($modified)) {
return $topic;
}
$values = $topic->getAttrs();
$fileds = $this->c->dbMap->topics;
$set = $vars = [];
foreach ($modified as $name) {
if (! isset($fileds[$name])) {
continue;
}
$vars[] = $values[$name];
$set[] = $name . '=?' . $fileds[$name];
}
if (empty($set)) {
return $topic;
}
$vars[] = $topic->id;
$set = \implode(', ', $set);
@ -62,20 +69,25 @@ class Save extends Action
if (null !== $topic->id) {
throw new RuntimeException('The model has ID');
}
$attrs = $topic->getAttrs();
$fileds = $this->c->dbMap->topics;
$set = $set2 = $vars = [];
foreach ($attrs as $key => $value) {
if (! isset($fileds[$key])) {
continue;
}
$vars[] = $value;
$set[] = $key;
$set2[] = '?' . $fileds[$key];
}
if (empty($set)) {
throw new RuntimeException('The model is empty');
}
$set = \implode(', ', $set);
$set2 = \implode(', ', $set2);
$query = "INSERT INTO ::topics ({$set})

View file

@ -24,6 +24,7 @@ class ChangeGroup extends Action
public function changeGroup(int $newGroupId, User ...$users): void
{
$newGroup = $this->c->groups->get($newGroupId);
if (
null === $newGroup
|| $newGroup->groupGuest
@ -35,6 +36,7 @@ class ChangeGroup extends Action
$moderators = [];
$adminPresent = $newGroup->groupAdmin;
$unverPresent = false;
foreach ($users as $user) {
if ($user->isGuest) {
throw new RuntimeException('Guest can not change group');
@ -59,6 +61,7 @@ class ChangeGroup extends Action
if (! empty($moderators)) {
$root = $this->c->forums->get(0); //???? вызов от группы админов?
if ($root instanceof Forum) {
foreach ($this->c->forums->depthList($root, 0) as $forum) {
$forum->modDelete(...$moderators);

View file

@ -207,8 +207,10 @@ class Current extends Action
if (! empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$langs = $this->c->Func->getLangs();
$main = [];
foreach ($this->c->Func->langParse($_SERVER['HTTP_ACCEPT_LANGUAGE']) as $entry) {
$arr = \explode('-', $entry, 2);
if (isset($arr[1])) {
$entry = $arr[0] . '_' . \strtoupper($arr[1]);
$main[] = $arr[0];
@ -217,6 +219,7 @@ class Current extends Action
return $langs[$entry];
}
}
if (! empty($main)) {
foreach ($main as $entry) {
if (isset($langs[$entry])) {

View file

@ -81,6 +81,7 @@ class Delete extends Action
if ($resetAdmin) {
$this->c->admins->reset();
}
$this->c->stats->reset();
}
}

View file

@ -35,8 +35,10 @@ class Filter extends Action
) {
throw new InvalidArgumentException('The sort direction is not defined');
}
$orderBy[] = "u.{$field} {$dir}";
}
if (empty($orderBy)) {
$orderBy = 'u.username ASC';
} else {
@ -50,6 +52,7 @@ class Filter extends Action
if (! isset($fields[$field])) {
throw new InvalidArgumentException("The '{$field}' field is not found");
}
switch ($rule[0]) {
case 'LIKE':
if (
@ -61,13 +64,16 @@ class Filter extends Action
$where[] = "u.{$field} {$like} ?{$fields[$field]} ESCAPE '#'";
$vars[] = \str_replace(['#', '%', '_', '*'], ['##', '#%', '#_', '%'], $rule[1]);
}
break;
}
$rule[0] = '=';
case '=':
case '!=':
$where[] = "u.{$field}{$rule[0]}?{$fields[$field]}";
$vars[] = $rule[1];
break;
case 'BETWEEN':
// если и min, и max
@ -96,6 +102,7 @@ class Filter extends Action
$where[] = "u.{$field}<=?{$fields[$field]}";
$vars[] = $rule[2];
}
break;
default:
throw new InvalidArgumentException('The condition is not defined');

View file

@ -71,6 +71,7 @@ class Load extends Action
$data = $this->c->DB->query($query, $vars)->fetchAll();
$result = [];
foreach ($data as $row) {
$result[] = $this->manager->create($row);
}

View file

@ -22,6 +22,7 @@ class UpdateCountPosts extends Action
public function updateCountPosts(mixed ...$args): void
{
$ids = [];
foreach ($args as $arg) {
if (
$arg instanceof User

View file

@ -22,6 +22,7 @@ class UpdateCountTopics extends Action
public function updateCountTopics(mixed ...$args): void
{
$ids = [];
foreach ($args as $arg) {
if (
$arg instanceof User

View file

@ -16,7 +16,7 @@ use RuntimeException;
class Users extends Manager
{
const CACHE_NAME = 'guest';
const CACHE_KEY = 'guest';
/**
* Ключ модели для контейнера
@ -147,13 +147,13 @@ class Users extends Manager
*/
public function guest(array $attrs = []): User
{
$cache = $this->c->Cache->get(self::CACHE_NAME);
$cache = $this->c->Cache->get(self::CACHE_KEY);
if (! \is_array($cache)) {
$cache = $this->c->groups->get(FORK_GROUP_GUEST)->getAttrs();
if (true !== $this->c->Cache->set(self::CACHE_NAME, $cache)) {
throw new RuntimeException('Unable to write value to cache - ' . self::CACHE_NAME);
if (true !== $this->c->Cache->set(self::CACHE_KEY, $cache)) {
throw new RuntimeException('Unable to write value to cache - ' . self::CACHE_KEY);
}
}
@ -176,8 +176,8 @@ class Users extends Manager
*/
public function resetGuest(): Users
{
if (true !== $this->c->Cache->delete(self::CACHE_NAME)) {
throw new RuntimeException('Unable to remove key from cache - ' . self::CACHE_NAME);
if (true !== $this->c->Cache->delete(self::CACHE_KEY)) {
throw new RuntimeException('Unable to remove key from cache - ' . self::CACHE_KEY);
}
return $this;

View file

@ -12,6 +12,8 @@ class PhpEngine
protected $separator;
protected $blocks;
protected $blockStack;
protected $templates = [];
/**
* Constructor