2018-03-04

This commit is contained in:
Visman 2018-03-04 18:44:12 +07:00
parent cda99fbe4b
commit 244e1649e9
11 changed files with 251 additions and 137 deletions

View file

@ -77,7 +77,7 @@ class Routing
// юзеры
if ($user->g_view_users == '1') {
// список пользователей
$r->add('GET', '/userlist[/{page:[1-9]\d*}]', 'Userlist:view', 'Userlist');
$r->add('GET', '/userlist[/{sort:username|registered|num_posts}/{dir:ASC|DESC}/{group:\-1|[1-9]\d*}/{name}][/{page:[1-9]\d*}]', 'Userlist:view', 'Userlist');
// юзеры
$r->add('GET', '/user/{id:[1-9]\d*}/{name}', 'Profile:view', 'User'); //????
}
@ -127,10 +127,10 @@ class Routing
}
$uri = $_SERVER['REQUEST_URI'];
if (($pos = strpos($uri, '?')) !== false) {
$uri = substr($uri, 0, $pos);
if (($pos = \strpos($uri, '?')) !== false) {
$uri = \substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);
$uri = \rawurldecode($uri);
$method = $_SERVER['REQUEST_METHOD'];
$route = $r->route($method, $uri);
@ -138,7 +138,7 @@ class Routing
switch ($route[0]) {
case $r::OK:
// ... 200 OK
list($page, $action) = explode(':', $route[1], 2);
list($page, $action) = \explode(':', $route[1], 2);
$page = $this->c->$page->$action($route[2], $method);
break;
case $r::NOT_FOUND:
@ -151,7 +151,7 @@ class Routing
break;
case $r::METHOD_NOT_ALLOWED:
// ... 405 Method Not Allowed
$page = $this->c->Message->message('Bad request', true, 405, ['Allow: ' . implode(',', $route[1])]);
$page = $this->c->Message->message('Bad request', true, 405, ['Allow: ' . \implode(',', $route[1])]);
break;
case $r::NOT_IMPLEMENTED:
// ... 501 Not implemented

View file

@ -77,9 +77,9 @@ class Router
public function __construct($base)
{
$this->baseUrl = $base;
$this->host = parse_url($base, PHP_URL_HOST);
$this->prefix = parse_url($base, PHP_URL_PATH);
$this->length = strlen($this->prefix);
$this->host = \parse_url($base, PHP_URL_HOST);
$this->prefix = \parse_url($base, PHP_URL_PATH);
$this->length = \strlen($this->prefix);
}
/**
@ -93,9 +93,9 @@ class Router
*/
public function validate($url, $defMarker, array $defArgs = [])
{
if (is_string($url)
&& parse_url($url, PHP_URL_HOST) === $this->host
&& ($route = $this->route('GET', rawurldecode(parse_url($url, PHP_URL_PATH))))
if (\is_string($url)
&& \parse_url($url, PHP_URL_HOST) === $this->host
&& ($route = $this->route('GET', \rawurldecode(\parse_url($url, PHP_URL_PATH))))
&& $route[0] === self::OK
) {
if (isset($route[3])) {
@ -119,7 +119,7 @@ class Router
public function link($marker = null, array $args = [])
{
$result = $this->baseUrl;
$anchor = isset($args['#']) ? '#' . rawurlencode($args['#']) : '';
$anchor = isset($args['#']) ? '#' . \rawurlencode($args['#']) : '';
// маркер пустой
if (null === $marker) {
@ -128,7 +128,7 @@ class Router
} elseif (! isset($this->links[$marker])) {
return $result . '/';
// ссылка статична
} elseif (is_string($data = $this->links[$marker])) {
} elseif (\is_string($data = $this->links[$marker])) {
return $result . $data . $anchor;
}
@ -140,7 +140,7 @@ class Router
if (isset($args[$name])) {
// кроме page = 1
if ($name !== 'page' || $args[$name] !== 1) {
$data['{' . $name . '}'] = rawurlencode(str_replace($this->subSearch, $this->subRepl, $args[$name]));
$data['{' . $name . '}'] = \rawurlencode(\str_replace($this->subSearch, $this->subRepl, $args[$name]));
continue;
}
}
@ -151,12 +151,12 @@ class Router
// значение не обязательно
} else {
// $link = preg_replace('%\[[^\[\]{}]*{' . preg_quote($name, '%') . '}[^\[\]{}]*\]%', '', $link);
$link = preg_replace('%\[[^\[\]]*?{' . preg_quote($name, '%') . '}[^\[\]]*+(\[((?>[^\[\]]*+)|(?1))+\])*?\]%', '', $link);
$link = \preg_replace('%\[[^\[\]]*?{' . \preg_quote($name, '%') . '}[^\[\]]*+(\[((?>[^\[\]]*+)|(?1))+\])*?\]%', '', $link);
}
}
$link = str_replace(['[', ']'], '', $link);
$link = \str_replace(['[', ']'], '', $link);
return $result . strtr($link, $data) . $anchor;
return $result . \strtr($link, $data) . $anchor;
}
/**
@ -176,8 +176,8 @@ class Router
}
if ($this->length) {
if (0 === strpos($uri, $this->prefix)) {
$uri = substr($uri, $this->length);
if (0 === \strpos($uri, $this->prefix)) {
$uri = \substr($uri, $this->length);
} else {
return [self::NOT_FOUND];
}
@ -193,16 +193,16 @@ class Router
list($handler, $marker) = $this->statical[$uri]['GET'];
return [self::OK, $handler, [], $marker];
} else {
$allowed = array_keys($this->statical[$uri]);
$allowed = \array_keys($this->statical[$uri]);
}
}
$pos = strpos($uri, '/', 1);
$base = false === $pos ? $uri : substr($uri, 0, $pos);
$pos = \strpos($uri, '/', 1);
$base = false === $pos ? $uri : \substr($uri, 0, $pos);
if (isset($this->dynamic[$base])) {
foreach ($this->dynamic[$base] as $pattern => $data) {
if (! preg_match($pattern, $uri, $matches)) {
if (! \preg_match($pattern, $uri, $matches)) {
continue;
}
@ -211,14 +211,14 @@ class Router
} elseif ($head && isset($data['GET'])) {
list($handler, $keys, $marker) = $data['GET'];
} else {
$allowed += array_keys($data);
$allowed += \array_keys($data);
continue;
}
$args = [];
foreach ($keys as $key) {
if (isset($matches[$key])) {
$args[$key] = str_replace($this->subRepl, $this->subSearch, $matches[$key]);
if (isset($matches[$key])) { // ???? может isset($matches[$key]{0}) тут поставить?
$args[$key] = isset($matches[$key]{0}) ? \str_replace($this->subRepl, $this->subSearch, $matches[$key]) : null;
}
}
return [self::OK, $handler, $args, $marker];
@ -241,7 +241,7 @@ class Router
*/
public function add($method, $route, $handler, $marker = null)
{
if (is_array($method)) {
if (\is_array($method)) {
foreach ($method as $m) {
$this->methods[$m] = 1;
}
@ -251,14 +251,14 @@ class Router
$link = $route;
$anchor = '';
if (false !== strpos($route, '#')) {
list($route, $anchor) = explode('#', $route, 2);
if (false !== \strpos($route, '#')) {
list($route, $anchor) = \explode('#', $route, 2);
$anchor = '#' . $anchor;
}
if (false === strpbrk($route, '{}[]')) {
if (false === \strpbrk($route, '{}[]')) {
$data = null;
if (is_array($method)) {
if (\is_array($method)) {
foreach ($method as $m) {
$this->statical[$route][$m] = [$handler, $marker];
}
@ -270,7 +270,7 @@ class Router
if (false === $data) {
throw new InvalidArgumentException('Route is incorrect');
}
if (is_array($method)) {
if (\is_array($method)) {
foreach ($method as $m) {
$this->dynamic[$data[0]][$data[1]][$m] = [$handler, $data[2], $marker];
}
@ -297,7 +297,7 @@ class Router
*/
protected function parse($route)
{
$parts = preg_split('%([\[\]{}/])%', $route, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$parts = \preg_split('%([\[\]{}/])%', $route, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$s = 1;
$base = $parts[0];
@ -325,11 +325,11 @@ class Router
case '{':
return false;
case '}':
$data = explode(':', $buffer, 2);
$data = \explode(':', $buffer, 2);
if (! isset($data[1])) {
$data[1] = '[^/\x00-\x1f]+';
}
if ($data[0] === '' || $data[1] === '' || is_numeric($data[0]{0})) {
if ($data[0] === '' || $data[1] === '' || \is_numeric($data[0]{0})) {
return false;
}
$pattern .= '(?P<' . $data[0] . '>' . $data[1] . ')';
@ -346,7 +346,7 @@ class Router
switch ($part) {
case '/':
$first = false;
$pattern .= preg_quote($part, '%');
$pattern .= \preg_quote($part, '%');
$temp .= $part;
break;
default:
@ -376,7 +376,7 @@ class Router
case '}':
return false;
default:
$pattern .= preg_quote($part, '%');
$pattern .= \preg_quote($part, '%');
$temp .= $part;
}
}

View file

@ -144,7 +144,7 @@ class Validator
*/
public function addValidators(array $validators)
{
$this->validators = array_replace($this->validators, $validators);
$this->validators = \array_replace($this->validators, $validators);
return $this;
}
@ -162,13 +162,13 @@ class Validator
foreach ($list as $field => $raw) {
$suffix = null;
// правило для элементов массива
if (strpos($field, '.') > 0) {
list($field, $suffix) = explode('.', $field, 2);
if (\strpos($field, '.') > 0) {
list($field, $suffix) = \explode('.', $field, 2);
}
$rules = [];
// перебор правил для текущего поля
foreach (explode('|', $raw) as $rule) { //???? нужно экоанирование для разделителей
$tmp = explode(':', $rule, 2);
foreach (\explode('|', $raw) as $rule) { //???? нужно экоанирование для разделителей
$tmp = \explode(':', $rule, 2);
if (empty($this->validators[$tmp[0]])) {
throw new RuntimeException($tmp[0] . ' validator not found');
}
@ -193,7 +193,7 @@ class Validator
*/
public function addArguments(array $arguments)
{
$this->arguments = array_replace($this->arguments, $arguments);
$this->arguments = \array_replace($this->arguments, $arguments);
return $this;
}
@ -206,7 +206,7 @@ class Validator
*/
public function addMessages(array $messages)
{
$this->messages = array_replace($this->messages, $messages);
$this->messages = \array_replace($this->messages, $messages);
return $this;
}
@ -219,7 +219,7 @@ class Validator
*/
public function addAliases(array $aliases)
{
$this->aliases = array_replace($this->aliases, $aliases);
$this->aliases = \array_replace($this->aliases, $aliases);
return $this;
}
@ -318,7 +318,7 @@ class Validator
$value = $this->validators[$validator]($this, $value, $attr, $this->getArguments($field, $validator));
array_pop($this->curData);
\array_pop($this->curData);
if (null !== $this->error) {
break;
@ -337,7 +337,7 @@ class Validator
*/
public function addError($error, $type = 'v')
{
if (empty($vars = end($this->curData))) {
if (empty($vars = \end($this->curData))) {
throw new RuntimeException('The array of variables is empty');
}
@ -347,7 +347,7 @@ class Validator
return;
}
extract($vars);
\extract($vars);
// псевдоним имени поля
$alias = isset($this->aliases[$field]) ? $this->aliases[$field] : $field;
@ -358,7 +358,7 @@ class Validator
} elseif (isset($this->messages[$field])) {
$error = $this->messages[$field];
}
if (is_array($error)) {
if (\is_array($error)) {
$type = $error[1];
$error = $error[0];
}
@ -441,11 +441,11 @@ class Validator
protected function vRequired($v, $value)
{
if (is_string($value)) {
if (strlen(preg_replace('%^\s+|\s+$%u', '', $value)) > 0) {
if (\is_string($value)) {
if (\strlen(\preg_replace('%^\s+|\s+$%u', '', $value)) > 0) {
return $value;
}
} elseif (is_array($value)) {
} elseif (\is_array($value)) {
if (! empty($value)) {
return $value;
}
@ -458,7 +458,7 @@ class Validator
protected function vRequiredWith($v, $value, $attr) //???????????????????????
{
foreach (explode(',', $attr) as $field) {
foreach (\explode(',', $attr) as $field) {
if (null !== $this->__get($field)) { // если есть хотя бы одно поле,
return $this->vRequired($v, $value); // то проверяем данное поле
} // на обязательное наличие
@ -480,17 +480,17 @@ class Validator
{
if (null === $value) {
return null;
} elseif (is_string($value)) {
foreach(explode(',', $attr) as $action) {
} elseif (\is_string($value)) {
foreach(\explode(',', $attr) as $action) {
switch ($action) {
case 'trim':
$value = preg_replace('%^\s+|\s+$%u', '', $value);
$value = \preg_replace('%^\s+|\s+$%u', '', $value);
break;
case 'lower':
$value = mb_strtolower($value, 'UTF-8');
$value = \mb_strtolower($value, 'UTF-8');
break;
case 'spaces':
$value = preg_replace('%\s+%u', ' ', $value);
$value = \preg_replace('%\s+%u', ' ', $value);
break;
}
}
@ -505,7 +505,7 @@ class Validator
{
if (null === $value) {
return null;
} elseif (is_numeric($value)) {
} elseif (\is_numeric($value)) {
return 0 + $value;
} else {
$this->addError('The :alias must be numeric');
@ -517,7 +517,7 @@ class Validator
{
if (null === $value) {
return null;
} elseif (is_numeric($value) && is_int(0 + $value)) {
} elseif (\is_numeric($value) && \is_int(0 + $value)) {
return (int) $value;
} else {
$this->addError('The :alias must be integer');
@ -527,14 +527,14 @@ class Validator
protected function vArray($v, $value, $attr)
{
if (null !== $value && ! is_array($value)) {
if (null !== $value && ! \is_array($value)) {
$this->addError('The :alias must be array');
return null;
} elseif (! $attr) {
return $value;
}
if (empty($vars = end($this->curData))) {
if (empty($vars = \end($this->curData))) {
throw new RuntimeException('The array of variables is empty');
}
@ -547,12 +547,12 @@ class Validator
protected function recArray(&$value, &$result, $name, $rules, $field)
{
$idxs = explode('.', $name);
$key = array_shift($idxs);
$name = implode('.', $idxs);
$idxs = \explode('.', $name);
$key = \array_shift($idxs);
$name = \implode('.', $idxs);
if ('*' === $key) {
if (! is_array($value)) {
if (! \is_array($value)) {
return; //????
}
@ -564,7 +564,7 @@ class Validator
}
}
} else {
if (! array_key_exists($key, $value)) {
if (! \array_key_exists($key, $value)) {
return; //????
}
@ -580,18 +580,18 @@ class Validator
protected function vMin($v, $value, $attr)
{
if (is_string($value)) {
if ((strpos($attr, 'bytes') && strlen($value) < (int) $attr)
|| mb_strlen($value, 'UTF-8') < $attr
if (\is_string($value)) {
if ((\strpos($attr, 'bytes') && \strlen($value) < (int) $attr)
|| \mb_strlen($value, 'UTF-8') < $attr
) {
$this->addError('The :alias minimum is :attr characters');
}
} elseif (is_numeric($value)) {
} elseif (\is_numeric($value)) {
if (0 + $value < $attr) {
$this->addError('The :alias minimum is :attr');
}
} elseif (is_array($value)) {
if (count($value) < $attr) {
} elseif (\is_array($value)) {
if (\count($value) < $attr) {
$this->addError('The :alias minimum is :attr elements');
}
} elseif (null !== $value) {
@ -603,17 +603,17 @@ class Validator
protected function vMax($v, $value, $attr)
{
if (is_string($value)) {
if ((strpos($attr, 'bytes') && strlen($value) > (int) $attr)
|| mb_strlen($value, 'UTF-8') > $attr
if (\is_string($value)) {
if ((\strpos($attr, 'bytes') && \strlen($value) > (int) $attr)
|| \mb_strlen($value, 'UTF-8') > $attr
) {
$this->addError('The :alias maximum is :attr characters');
}
} elseif (is_numeric($value)) {
} elseif (\is_numeric($value)) {
if (0 + $value > $attr) {
$this->addError('The :alias maximum is :attr');
}
} elseif (is_array($value)) {
} elseif (\is_array($value)) {
if (count($value) > $attr) {
$this->addError('The :alias maximum is :attr elements');
}
@ -626,10 +626,10 @@ class Validator
protected function vToken($v, $value, $attr, $args)
{
if (! is_array($args)) {
if (! \is_array($args)) {
$args = [];
}
if (! is_string($value) || ! $this->c->Csrf->verify($value, $attr, $args)) {
if (! \is_string($value) || ! $this->c->Csrf->verify($value, $attr, $args)) {
$this->addError('Bad token', 'e');
return null;
} else {
@ -644,7 +644,7 @@ class Validator
protected function vReferer($v, $value, $attr, $args)
{
if (! is_array($args)) {
if (! \is_array($args)) {
$args = [];
}
return $this->c->Router->validate($value, $attr, $args);
@ -677,7 +677,7 @@ class Validator
protected function vRegex($v, $value, $attr)
{
if (null !== $value
&& (! is_string($value) || ! preg_match($attr, $value))
&& (! is_string($value) || ! \preg_match($attr, $value))
) {
$this->addError('The :alias is not valid format');
return null;
@ -698,7 +698,7 @@ class Validator
protected function vIn($v, $value, $attr)
{
if (null !== $value && ! in_array($value, explode(',', $attr))) {
if (null !== $value && ! \in_array($value, \explode(',', $attr))) {
$this->addError('The :alias contains an invalid value');
}
return $value;
@ -706,7 +706,7 @@ class Validator
protected function vNotIn($v, $value, $attr)
{
if (null !== $value && in_array($value, explode(',', $attr))) {
if (null !== $value && \in_array($value, \explode(',', $attr))) {
$this->addError('The :alias contains an invalid value');
}
return $value;

View file

@ -34,8 +34,8 @@ class Options extends Admin
'o_board_desc' => 'string:trim|max:65000 bytes',
'o_default_timezone' => 'required|string:trim|in:-12,-11,-10,-9.5,-9,-8.5,-8,-7,-6,-5,-4,-3.5,-3,-2,-1,0,1,2,3,3.5,4,4.5,5,5.5,5.75,6,6.5,7,8,8.75,9,9.5,10,10.5,11,11.5,12,12.75,13,14',
'o_default_dst' => 'required|integer|in:0,1',
'o_default_lang' => 'required|string:trim|in:' . implode(',', $this->c->Func->getLangs()),
'o_default_style' => 'required|string:trim|in:' . implode(',', $this->c->Func->getStyles()),
'o_default_lang' => 'required|string:trim|in:' . \implode(',', $this->c->Func->getLangs()),
'o_default_style' => 'required|string:trim|in:' . \implode(',', $this->c->Func->getStyles()),
'o_time_format' => 'required|string:trim|max:25',
'o_date_format' => 'required|string:trim|max:25',
'o_timeout_visit' => 'required|integer|min:0|max:99999',
@ -49,6 +49,7 @@ class Options extends Admin
'o_topic_review' => 'required|integer|min:0|max:50',
'o_disp_topics_default' => 'required|integer|min:10|max:50',
'o_disp_posts_default' => 'required|integer|min:10|max:50',
'o_disp_users' => 'required|integer|min:10|max:50',
'o_indent_num_spaces' => 'required|integer|min:0|max:99',
'o_quote_depth' => 'required|integer|min:0|max:9',
'o_quickpost' => 'required|integer|in:0,1',
@ -155,7 +156,7 @@ class Options extends Admin
*/
public function vCheckDir(Validator $v, $dir)
{
$dir = '/' . trim(str_replace(['\\', '.'], ['/', ''], $dir), '/'); //?????
$dir = '/' . \trim(\str_replace(['\\', '.'], ['/', ''], $dir), '/'); //?????
return $dir;
}
@ -171,7 +172,7 @@ class Options extends Admin
*/
public function vCheckEmpty(Validator $v, $value, $attr)
{
if (0 !== $value && 0 === strlen($v->$attr)) {
if (0 !== $value && 0 === \strlen($v->$attr)) {
$value = 0;
}
return $value;
@ -203,9 +204,9 @@ class Options extends Admin
$yn = [1 => \ForkBB\__('Yes'), 0 => \ForkBB\__('No')];
$langs = $this->c->Func->getLangs();
$langs = array_combine($langs, $langs);
$langs = \array_combine($langs, $langs);
$styles = $this->c->Func->getStyles();
$styles = array_combine($styles, $styles);
$styles = \array_combine($styles, $styles);
$form['sets'][] = [
'legend' => \ForkBB\__('Essentials subhead'),
@ -297,7 +298,7 @@ class Options extends Admin
],
];
$timestamp = time() + ($this->user->timezone + $this->user->dst) * 3600;
$timestamp = \time() + ($this->user->timezone + $this->user->dst) * 3600;
$time = \ForkBB\dt($timestamp, false, $config->o_date_format, $config->o_time_format, true, true);
$date = \ForkBB\dt($timestamp, true, $config->o_date_format, $config->o_time_format, false, true);
@ -385,14 +386,6 @@ class Options extends Admin
'title' => \ForkBB\__('Clickable links label'),
'info' => \ForkBB\__('Clickable links help'),
],
'o_topic_review' => [
'type' => 'number',
'min' => 0,
'max' => 50,
'value' => $config->o_topic_review,
'title' => \ForkBB\__('Topic review label'),
'info' => \ForkBB\__('Topic review help'),
],
'o_disp_topics_default' => [
'type' => 'number',
'min' => 10,
@ -409,6 +402,22 @@ class Options extends Admin
'title' => \ForkBB\__('Posts per page label'),
'info' => \ForkBB\__('Posts per page help'),
],
'o_disp_users' => [
'type' => 'number',
'min' => 10,
'max' => 50,
'value' => $config->o_disp_users,
'title' => \ForkBB\__('Users per page label'),
'info' => \ForkBB\__('Users per page help'),
],
'o_topic_review' => [
'type' => 'number',
'min' => 0,
'max' => 50,
'value' => $config->o_topic_review,
'title' => \ForkBB\__('Topic review label'),
'info' => \ForkBB\__('Topic review help'),
],
'o_indent_num_spaces' => [
'type' => 'number',
'min' => 0,

View file

@ -35,7 +35,7 @@ class Install extends Page
$dbTypes = [];
$pdoDrivers = PDO::getAvailableDrivers();
foreach ($pdoDrivers as $type) {
if (file_exists($this->c->DIR_APP . '/Core/DB/' . ucfirst($type) . '.php')) {
if (\file_exists($this->c->DIR_APP . '/Core/DB/' . \ucfirst($type) . '.php')) {
switch ($type) {
case 'mysql':
$dbTypes['mysql_innodb'] = 'MySQL InnoDB (PDO)';
@ -48,7 +48,7 @@ class Install extends Page
$dbTypes[$type] = 'PostgreSQL (PDO)';
break;
default:
$dbTypes[$type] = ucfirst($type) . ' (PDO)';
$dbTypes[$type] = \ucfirst($type) . ' (PDO)';
}
}
}
@ -84,7 +84,7 @@ class Install extends Page
$this->c->Lang->load('install');
// версия PHP
if (version_compare(PHP_VERSION, self::PHP_MIN, '<')) {
if (\version_compare(PHP_VERSION, self::PHP_MIN, '<')) {
$this->fIswev = ['e', \ForkBB\__('You are running error', 'PHP', PHP_VERSION, $this->c->FORK_REVISION, self::PHP_MIN)];
}
@ -101,14 +101,14 @@ class Install extends Page
$this->c->DIR_PUBLIC . '/img/avatars',
];
foreach ($folders as $folder) {
if (! is_writable($folder)) {
$folder = str_replace(dirname($this->c->DIR_APP), '', $folder);
if (! \is_writable($folder)) {
$folder = \str_replace(\dirname($this->c->DIR_APP), '', $folder);
$this->fIswev = ['e', \ForkBB\__('Alert folder', $folder)];
}
}
// доступность шаблона конфигурации
$config = @file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
$config = @\file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
if (false === $config) {
$this->fIswev = ['e', \ForkBB\__('No access to main.dist.php')];
}
@ -133,7 +133,7 @@ class Install extends Page
'check_host' => [$this, 'vCheckHost'],
'rtrim_url' => [$this, 'vRtrimURL']
])->addRules([
'dbtype' => 'required|string:trim|in:' . implode(',', array_keys($this->dbTypes)),
'dbtype' => 'required|string:trim|in:' . \implode(',', \array_keys($this->dbTypes)),
'dbhost' => 'required|string:trim|check_host',
'dbname' => 'required|string:trim',
'dbuser' => 'string:trim',
@ -145,8 +145,8 @@ class Install extends Page
'title' => 'required|string:trim|max:255',
'descr' => 'string:trim|max:65000 bytes',
'baseurl' => 'required|string:trim|rtrim_url',
'defaultlang' => 'required|string:trim|in:' . implode(',', $this->c->Func->getLangs()),
'defaultstyle' => 'required|string:trim|in:' . implode(',', $this->c->Func->getStyles()),
'defaultlang' => 'required|string:trim|in:' . \implode(',', $this->c->Func->getLangs()),
'defaultstyle' => 'required|string:trim|in:' . \implode(',', $this->c->Func->getStyles()),
])->addAliases([
'dbtype' => 'Database type',
'dbhost' => 'Database server hostname',
@ -172,7 +172,7 @@ class Install extends Page
}
}
if (count($langs) > 1) {
if (\count($langs) > 1) {
$this->form1 = [
'action' => $this->c->Router->link('Install'),
'hidden' => [
@ -183,7 +183,7 @@ class Install extends Page
'fields' => [
'installlang' => [
'type' => 'select',
'options' => array_combine($langs, $langs),
'options' => \array_combine($langs, $langs),
'value' => $this->user->language,
'title' => \ForkBB\__('Install language'),
'info' => \ForkBB\__('Choose install language info'),
@ -387,7 +387,7 @@ class Install extends Page
*/
public function vRtrimURL(Validator $v, $url)
{
return rtrim($url, '/');
return \rtrim($url, '/');
}
/**
@ -401,9 +401,9 @@ class Install extends Page
public function vCheckPrefix(Validator $v, $prefix)
{
if (isset($prefix{0})) {
if (! preg_match('%^[a-z][a-z\d_]*$%i', $prefix)) {
if (! \preg_match('%^[a-z][a-z\d_]*$%i', $prefix)) {
$v->addError('Table prefix error');
} elseif ('sqlite' === $v->dbtype && 'sqlite_' === strtolower($prefix)) {
} elseif ('sqlite' === $v->dbtype && 'sqlite_' === \strtolower($prefix)) {
$v->addError('Prefix reserved');
}
}
@ -438,7 +438,7 @@ class Install extends Page
$DBEngine = 'InnoDB';
case 'mysql':
$this->DBEngine = $DBEngine;
if (preg_match('%^([^:]+):(\d+)$%', $dbhost, $matches)) {
if (\preg_match('%^([^:]+):(\d+)$%', $dbhost, $matches)) {
$this->c->DB_DSN = "mysql:host={$matches[1]};port={$matches[2]};dbname={$dbname};charset=utf8mb4";
} else {
$this->c->DB_DSN = "mysql:host={$dbhost};dbname={$dbname};charset=utf8mb4";
@ -489,7 +489,7 @@ class Install extends Page
*/
protected function installEnd(Validator $v)
{
@set_time_limit(0);
@\set_time_limit(0);
$this->c->Cache->clear();
$this->c->DB->beginTransaction();
@ -1034,7 +1034,7 @@ class Install extends Page
}
$this->c->DB->exec('UPDATE ::groups SET g_pm_limit=0 WHERE g_id=?i', [$this->c->GROUP_ADMIN]);
$ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?: 'unknow';
$ip = \filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?: 'unknow';
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password, email) VALUES (?i, ?s, ?s, ?s)', [$this->c->GROUP_GUEST, \ForkBB\__('Guest '), \ForkBB\__('Guest '), \ForkBB\__('Guest ')]);
$this->c->DB->exec('INSERT INTO ::users (group_id, username, password, email, language, style, num_posts, last_post, registered, registration_ip, last_visit) VALUES (?i, ?s, ?s, ?s, ?s, ?s, ?i, ?i, ?i, ?s, ?i)', [$this->c->GROUP_ADMIN, $v->username, password_hash($v->password, PASSWORD_DEFAULT), $v->email, $v->defaultlang, $v->defaultstyle, 1, $now, $now, $ip, $now]);
@ -1061,6 +1061,7 @@ class Install extends Page
'o_topic_review' => 15,
'o_disp_topics_default' => 30,
'o_disp_posts_default' => 25,
'o_disp_users' => 50,
'o_indent_num_spaces' => 4,
'o_quote_depth' => 3,
'o_quickpost' => 1,
@ -1075,7 +1076,7 @@ class Install extends Page
'o_regs_report' => 0,
'o_default_email_setting' => 1,
'o_mailing_list' => $v->email,
'o_avatars' => in_array(strtolower(@ini_get('file_uploads')), ['on', 'true', '1']) ? 1 : 0,
'o_avatars' => \in_array(\strtolower(@\ini_get('file_uploads')), ['on', 'true', '1']) ? 1 : 0,
'o_avatars_dir' => '/img/avatars',
'o_avatars_width' => 60,
'o_avatars_height' => 60,
@ -1168,7 +1169,7 @@ class Install extends Page
$this->c->DB->commit();
$config = @file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
$config = @\file_get_contents($this->c->DIR_CONFIG . '/main.dist.php');
if (false === $config) {
throw new RuntimeException('No access to main.dist.php.');
}
@ -1185,9 +1186,9 @@ class Install extends Page
'_COOKIE_KEY2_' => $this->c->Secury->randomPass(mt_rand(20,30)),
];
foreach ($repl as $key => $val) {
$config = str_replace($key, addslashes($val), $config);
$config = \str_replace($key, \addslashes($val), $config);
}
$result = file_put_contents($this->c->DIR_CONFIG . '/main.php', $config);
$result = \file_put_contents($this->c->DIR_CONFIG . '/main.php', $config);
if (false === $result) {
throw new RuntimeException('No write to main.php');
}

View file

@ -11,8 +11,6 @@ class Userlist extends Page
{
use CrumbTrait;
protected $usersPerPage = 2; // ???? в конфиг!
/**
* Список пользователей
*
@ -25,18 +23,53 @@ class Userlist extends Page
{
$this->c->Lang->load('userlist');
$ids = $this->c->users->filter([], []);
$v = $this->c->Validator->reset()
->addRules([
'sort' => 'string|in:username,registered,num_posts',
'dir' => 'string|in:ASC,DESC',
'group' => 'integer|min:-1|max:9999999999|not_in:0,' . $this->c->GROUP_GUEST,
'name' => 'string:trim|min:1|max:25',
]);
$error = true;
if ($v->validation($args)) {
$count = (int) (null === $v->sort)
+ (int) (null === $v->dir)
+ (int) (null === $v->group)
+ (int) (null === $v->name);
if (0 === $count || 4 === $count) {
$error = false;
}
}
if ($error) {
return $this->c->Message->message('Bad request');
}
$filters = [];
if ($v->group < 1) {
$filters['group_id'] = ['!=', 0];
} else {
$filters['group_id'] = ['=', $v->group];
}
if (null !== $v->name && '*' !== $v->name) {
$filters['username'] = ['LIKE', $v->name];
}
$order = $v->sort ? [$v->sort => $v->dir] : [];
$ids = $this->c->users->filter($filters, $order);
$number = \count($ids);
$page = isset($args['page']) ? (int) $args['page'] : 1;
$pages = $number ? (int) \ceil($number / $this->usersPerPage) : 1;
$pages = $number ? (int) \ceil($number / $this->c->config->o_disp_users) : 1;
if ($page > $pages) {
return $this->c->Message->message('Bad request');
}
if ($number) {
$this->startNum = ($page - 1) * $this->usersPerPage;
$ids = \array_slice($ids, $this->startNum, $this->usersPerPage);
$this->startNum = ($page - 1) * $this->c->config->o_disp_users;
$ids = \array_slice($ids, $this->startNum, $this->c->config->o_disp_users);
$this->userList = $this->c->users->load($ids);
} else {
$this->startNum = 0;
@ -51,7 +84,7 @@ class Userlist extends Page
$this->robots = 'noindex';
// $this->form = $form;
$this->crumbs = $this->crumbs([$this->c->Router->link('Userlist'), \ForkBB\__('User_list')]);
$this->pagination = $this->c->Func->paginate($pages, $page, 'Userlist');
$this->pagination = $this->c->Func->paginate($pages, $page, 'Userlist', $args);
return $this;
}

View file

@ -20,18 +20,18 @@ class Filter extends Action
*/
public function filter(array $filters, array $order = [])
{
$fileds = $this->c->dbMap->users;
$fields = $this->c->dbMap->users;
$orderBy = [];
$where = ['u.id>1'];
foreach ($order as $filed => $val) {
if (! isset($fileds[$filed])) {
foreach ($order as $field => $dir) {
if (! isset($fields[$field])) {
throw new InvalidArgumentException('No sorting field found');
}
if ('ACS' !== $val && 'DESC' !== $val) {
if ('ASC' !== $dir && 'DESC' !== $dir) {
throw new InvalidArgumentException('The sorting order is not clear');
}
$orderBy[] = "u.{$filed} {$val}";
$orderBy[] = "u.{$field} {$dir}";
}
if (empty($orderBy)) {
$orderBy = 'u.username ASC';
@ -39,9 +39,29 @@ class Filter extends Action
$orderBy = \implode(', ', $orderBy);
}
$vars = [];
foreach ($filters as $field => $rule) {
if (! isset($fields[$field])) {
throw new InvalidArgumentException('No sorting field found');
}
switch ($rule[0]) {
case '=':
case '!=':
$where[] = "u.{$field}{$rule[0]}?{$fields[$field]}";
$vars[] = $rule[1];
break;
case 'LIKE':
$where[] = "u.{$field} LIKE ?{$fields[$field]}";
$vars[] = \str_replace(['*', '_'], ['%', '\\_'], $rule[1]);
break;
default:
throw new InvalidArgumentException('The condition is not clear');
}
}
$where = \implode(' AND ', $where);
$vars = [];
$sql = "SELECT u.id
FROM ::users AS u
WHERE {$where}

View file

@ -279,6 +279,12 @@ msgstr "Posts per page"
msgid "Posts per page help"
msgstr "The default number of posts to display per page in a topic. Users can personalize this setting."
msgid "Users per page label"
msgstr "Users per page"
msgid "Users per page help"
msgstr "The number of users displayed on one page of the list."
msgid "Indent label"
msgstr "Indent size"

View file

@ -279,6 +279,12 @@ msgstr "Сообщений на страницу"
msgid "Posts per page help"
msgstr "Значение по умолчанию сколько сообщений выводить на странице с темой. Пользователь может установить своё значение."
msgid "Users per page label"
msgstr "Пользователей на страницу"
msgid "Users per page help"
msgstr "Число пользователей отображаемых на одной странице списка."
msgid "Indent label"
msgstr "Размер отступа"

View file

@ -55,12 +55,30 @@
<div class="f-ulist">
<ol class="f-table">
<li class="f-row f-thead" value="{{ $p->startNum }}">
<span class="f-hcell f-cusername">{!! __('Username') !!}</span>
<span class="f-hcell f-cusername">
<span class="f-hc-table">
<span class="f-hc-tasc">▲</span>
<span class="f-hc-tname">{!! __('Username') !!}</span>
<span class="f-hc-tdesc">▼</span>
</span>
</span>
<span class="f-hcell f-ctitle">{!! __('Title') !!}</span>
@if ($p->user->showPostCount)
<span class="f-hcell f-cnumposts">{!! __('Posts') !!}</span>
<span class="f-hcell f-cnumposts">
<span class="f-hc-table">
<span class="f-hc-tasc">▲</span>
<span class="f-hc-tname">{!! __('Posts') !!}</span>
<span class="f-hc-tdesc">▼</span>
</span>
</span>
@endif
<span class="f-hcell f-cdatereg">{!! __('Registered') !!}</span>
<span class="f-hcell f-cdatereg">
<span class="f-hc-table">
<span class="f-hc-tasc">▲</span>
<span class="f-hc-tname">{!! __('Registered') !!}</span>
<span class="f-hc-tdesc">▼</span>
</span>
</span>
</li>
@foreach ($p->userList as $user)
<li class="f-row">

View file

@ -1946,6 +1946,18 @@ li + li .f-btn {
display: none;
}
.f-ulist .f-hcell .f-hc-table {
display: table;
line-height: 1;
}
.f-hc-table .f-hc-tasc,
.f-hc-table .f-hc-tdesc {
font-size: 0.625rem;
display: block;
text-align: center;
}
.f-ulist .f-cell > b,
.f-ulist .f-cell > i {
font-style: normal;
@ -1970,9 +1982,18 @@ li + li .f-btn {
text-align: center;
}
.f-ulist .f-cnumposts .f-hc-table {
margin: 0 auto;
}
.f-ulist .f-cdatereg {
padding: 0.625rem;
width: 11rem;
min-width: 11rem;
}
.f-ulist .f-hcell {
padding-top: 0.3125rem;
padding-bottom: 0.3125rem;
}
}