* Admin -> Users

This commit is contained in:
Visman 2018-09-03 23:48:47 +07:00
parent 6fc06d2faf
commit 942b0f9afe
6 changed files with 197 additions and 28 deletions

View file

@ -125,7 +125,7 @@ class Routing
$r->add('GET', '/admin/statistics', 'AdminStatistics:statistics', 'AdminStatistics');
$r->add(['GET', 'POST'], '/admin/users', 'AdminUsers:view', 'AdminUsers');
$r->add('GET', '/admin/users/filter/{filters}/{hash}[/{page:[1-9]\d*}]', 'AdminUsers:filter', 'AdminShowUsersWithFilter');
$r->add('GET', '/admin/users/filter/{filters}/{hash}[/{page:[1-9]\d*}]', 'AdminUsers:viewFilter', 'AdminUsersFilter');
}
// только админ
@ -150,7 +150,8 @@ class Routing
$r->add('GET', '/admin/maintenance/rebuild/{token}/{clear:[01]}/{limit:[1-9]\d*}/{start:[1-9]\d*}', 'AdminMaintenance:rebuild', 'AdminRebuildIndex' );
$r->add('GET', '/admin/get/host/{ip:[0-9a-fA-F:.]+}', 'AdminHost:view', 'AdminHost');
$r->add('GET', '/admin/users/ip/{ip:[0-9a-fA-F:.]+}[/{page:[1-9]\d*}]', 'AdminUsers:ip', 'AdminShowUsersWithIP');
$r->add('GET', '/admin/users/ip/{ip:[0-9a-fA-F:.]+}[/{page:[1-9]\d*}]', 'AdminUsers:viewIP', 'AdminUsersIP');
$r->add('GET', '/admin/users/user/{id:[2-9]|[1-9]\d+}[/{page:[1-9]\d*}]', 'AdminUsers:viewUserStat', 'AdminUserStat');
}
$uri = $_SERVER['REQUEST_URI'];

View file

@ -28,7 +28,7 @@ class Host extends Admin
$this->nameTpl = 'message';
$this->titles = \ForkBB\__('Info');
$this->message = \ForkBB\__('Host info', $ip, $host, $this->c->Router->link('AdminShowUsersWithIP', ['ip' => $ip]));
$this->message = \ForkBB\__('Host info', $ip, $host, $this->c->Router->link('AdminUsersIP', ['ip' => $ip]));
$this->back = true;
return $this;

View file

@ -31,6 +31,47 @@ class Users extends Admin
return $onlyKeys ? \array_keys($groups) : $groups;
}
/**
* Подготавливает данные для шаблона ip статистики для пользователя
*
* @param array $args
* @param string $method
*
* @return Page
*/
public function viewUserStat(array $args, $method)
{
$this->c->Lang->load('admin_users');
$stat = $this->c->posts->userStat($args['id']);
$number = \count($stat);
$page = isset($args['page']) ? (int) $args['page'] : 1;
$pages = (int) \ceil(($number ?: 1) / $this->c->config->o_disp_users);
if ($page > $pages) {
return $this->c->Message->message('Bad request');
}
$startNum = ($page - 1) * $this->c->config->o_disp_users;
$stat = \array_slice($stat, $startNum, $this->c->config->o_disp_users);
$user = $this->c->users->load((int) $args['id']);
if (0 == $number) {
$this->fIswev = ['i', \ForkBB\__('Results no posts found')];
}
$this->nameTpl = 'admin/users_result';
$this->aIndex = 'users';
$this->mainSuffix = '-one-column';
$this->aCrumbs[] = [$this->c->Router->link('AdminUserStat', ['id' => $args['id']]), $user->username];
$this->formResult = $this->formStat($stat, $startNum);
$this->pagination = $this->c->Func->paginate($pages, $page, 'AdminUserStat', ['id' => $args['id']]);
return $this;
}
/**
* Подготавливает данные для шаблона найденных по ip пользователей
*
@ -39,7 +80,7 @@ class Users extends Admin
*
* @return Page
*/
public function ip(array $args, $method)
public function viewIP(array $args, $method)
{
$ip = \filter_var($args['ip'], \FILTER_VALIDATE_IP);
if (false === $ip) {
@ -69,7 +110,7 @@ class Users extends Admin
}
$page = isset($args['page']) ? (int) $args['page'] : 1;
$pages = (int) \ceil($number / $this->c->config->o_disp_users);
$pages = (int) \ceil(($number ?: 1) / $this->c->config->o_disp_users);
if ($page > $pages) {
return $this->c->Message->message('Bad request');
@ -82,9 +123,9 @@ class Users extends Admin
$this->nameTpl = 'admin/users_result';
$this->aIndex = 'users';
$this->mainSuffix = '-one-column';
$this->aCrumbs[] = [$this->c->Router->link('AdminShowUsersWithIP', ['ip' => $ip]), $ip];
$this->aCrumbs[] = [$this->c->Router->link('AdminUsersIP', ['ip' => $ip]), $ip];
$this->formResult = $this->formUsers($userList, $startNum);
$this->pagination = $this->c->Func->paginate($pages, $page, 'AdminShowUsersWithIP', ['ip' => $ip]);
$this->pagination = $this->c->Func->paginate($pages, $page, 'AdminUsersIP', ['ip' => $ip]);
return $this;
}
@ -97,7 +138,7 @@ class Users extends Admin
*
* @return Page
*/
public function filter(array $args, $method)
public function viewFilter(array $args, $method)
{
if (! \hash_equals($args['hash'], $this->c->Secury->hash($args['filters']))
|| ! \is_array($data = \json_decode(\base64_decode($args['filters'], true), true))
@ -150,7 +191,7 @@ class Users extends Admin
}
$page = isset($args['page']) ? (int) $args['page'] : 1;
$pages = (int) \ceil($number / $this->c->config->o_disp_users);
$pages = (int) \ceil(($number ?: 1) / $this->c->config->o_disp_users);
if ($page > $pages) {
return $this->c->Message->message('Bad request');
@ -163,9 +204,9 @@ class Users extends Admin
$this->nameTpl = 'admin/users_result';
$this->aIndex = 'users';
$this->mainSuffix = '-one-column';
$this->aCrumbs[] = [$this->c->Router->link('AdminShowUsersWithFilter', ['filters' => $args['filters'], 'hash' => $args['hash']]), \ForkBB\__('Results head')];
$this->aCrumbs[] = [$this->c->Router->link('AdminUsersFilter', ['filters' => $args['filters'], 'hash' => $args['hash']]), \ForkBB\__('Results head')];
$this->formResult = $this->formUsers($userList, $startNum);
$this->pagination = $this->c->Func->paginate($pages, $page, 'AdminShowUsersWithFilter', ['filters' => $args['filters'], 'hash' => $args['hash']]);
$this->pagination = $this->c->Func->paginate($pages, $page, 'AdminUsersFilter', ['filters' => $args['filters'], 'hash' => $args['hash']]);
return $this;
}
@ -197,7 +238,7 @@ class Users extends Admin
$this->fIswev = ['v', \ForkBB\__('Bad IP message')];
$data = $v->getData();
} else {
return $this->c->Redirect->page('AdminShowUsersWithIP', ['ip' => $ip]);
return $this->c->Redirect->page('AdminUsersIP', ['ip' => $ip]);
}
} else {
$v = $this->c->Validator->reset()
@ -254,7 +295,7 @@ class Users extends Admin
unset($filters['token']);
$filters = \base64_encode(\json_encode($filters));
$hash = $this->c->Secury->hash($filters);
return $this->c->Redirect->page('AdminShowUsersWithFilter', ['filters' => $filters, 'hash' => $hash]);
return $this->c->Redirect->page('AdminUsersFilter', ['filters' => $filters, 'hash' => $hash]);
}
$this->fIswev = $v->getErrors();
@ -611,7 +652,7 @@ class Users extends Admin
'title' => \ForkBB\__('Results show posts link'),
];
$fields["l{$number}-note"] = [
'class' => $user->isGuest ? ['result', 'note', 'no-data'] : ['result', 'note'],
'class' => '' === \trim($user->admin_note) ? ['result', 'note', 'no-data'] : ['result', 'note'],
'type' => 'str',
'caption' => \ForkBB\__('Примечание админа'),
'value' => $user->admin_note,
@ -620,10 +661,10 @@ class Users extends Admin
if ($this->user->isAdmin) {
$fields["l{$number}-view-ip"] = [
'class' => $user->isGuest ? ['result', 'view-ip', 'no-data'] : ['result', 'view-ip'],
'type' => $user->isGuest ? 'str' : 'link',
'type' => $user->isGuest || ! $user->num_posts ? 'str' : 'link',
'caption' => \ForkBB\__('Results action head'),
'value' => $user->isGuest ? null : \ForkBB\__('Results view IP link'),
'href' => '',
'href' => $this->c->Router->link('AdminUserStat', ['id' => $user->id]),
];
}
@ -632,7 +673,7 @@ class Users extends Admin
];
$key = $user->isGuest ? "guest{$number}" : "users[{$user->id}]";
$fields[$key] = [
'class' => ['result', 'check'],
'class' => ['check'],
'caption' => \ForkBB\__('Select'),
'type' => $user->isGuest ? 'str' : 'checkbox',
'value' => $user->isGuest ? null : $user->id,
@ -649,4 +690,67 @@ class Users extends Admin
return $form;
}
/**
* Создает массив данных для формы статистики пользователя по ip
*
* @param array $stat
* @param int $number
*
* @return array
*/
protected function formStat(array $stat, $number)
{
$form = [
'action' => null,
'hidden' => null,
'sets' => [],
'btns' => null,
];
\array_unshift($stat, ['last_used' => null, 'used_times' => null]);
$flag = false;
foreach ($stat as $ip => $data) {
$fields = [];
$fields["l{$number}-ip"] = [
'class' => ['result', 'ip'],
'type' => $flag ? 'link' : 'str',
'caption' => \ForkBB\__('Results IP address head'),
'value' => $flag ? $ip : null,
'href' => $flag ? $this->c->Router->link('AdminHost', ['ip' => $ip]) : null,
];
$fields["l{$number}-last-used"] = [
'class' => ['result', 'last-used'],
'type' => 'str',
'caption' => \ForkBB\__('Results last used head'),
'value' => $flag ? \ForkBB\dt($data['last_used']) : null,
];
$fields["l{$number}-used-times"] = [
'class' => ['result', 'used-times'],
'type' => 'str',
'caption' => \ForkBB\__('Results times found head'),
'value' => $flag ? \ForkBB\num($data['used_times']) : null,
];
$fields["l{$number}-action"] = [
'class' => ['result', 'action'],
'type' => $flag ? 'link' : 'str',
'caption' => \ForkBB\__('Results action head'),
'value' => $flag ? \ForkBB\__('Results find more link') : null,
'href' => $flag ? $this->c->Router->link('AdminUsersIP', ['ip' => $ip]) : null,
];
$form['sets']["l{$number}"] = [
'class' => ['result', 'stat'],
'legend' => $flag ? $number : null,
'fields' => $fields,
];
++$number;
$flag = true;
}
return $form;
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace ForkBB\Models\Post;
use ForkBB\Models\Action;
use ForkBB\Models\Post\Model as Post;
use PDO;
class UserStat extends Action
{
/**
* Возвращает массив данных использования ip для данного пользователя
*
* @param int $id
*
* @return array
*/
public function userStat($id)
{
$vars = [
':id' => $id,
];
$sql = 'SELECT p.poster_ip, MAX(p.posted) AS last_used, COUNT(p.id) AS used_times
FROM ::posts AS p
WHERE p.poster_id=?i:id
GROUP BY p.poster_ip
ORDER BY last_used DESC';
return $this->c->DB->query($sql, $vars)->fetchAll(PDO::FETCH_UNIQUE);
}
}

View file

@ -234,6 +234,7 @@ return [
'PostManagerView' => \ForkBB\Models\Post\View::class,
'PostManagerRebuildIndex' => \ForkBB\Models\Post\RebuildIndex::class,
'PostManagerUserInfoFromIP' => \ForkBB\Models\Post\UserInfoFromIP::class,
'PostManagerUserStat' => \ForkBB\Models\Post\UserStat::class,
'GroupModel' => \ForkBB\Models\Group\Model::class,
'GroupManager' => \ForkBB\Models\Group\Manager::class,

View file

@ -2294,6 +2294,10 @@ select {
padding-bottom: 0.3125rem;
}
.f-fs-stat {
display: block;
}
.f-fs-result:first-of-type,
.f-fs-result .f-field-no-data {
display: none;
@ -2316,22 +2320,24 @@ select {
width: calc(100% - 3rem);
}
.f-wrap-main-result .f-field-result > dt,
.f-wrap-main-result .f-field-result > dd,
.f-wrap-main-result .f-field-result .f-str {
.f-fs-result .f-field-result > dt,
.f-fs-result .f-field-result > dd,
.f-fs-result .f-field-result .f-str {
display: inline;
}
.f-wrap-main-result .f-field-result .f-child1 {
.f-fs-result .f-field-result .f-child1 {
display: inline;
font-weight: bold;
}
.f-wrap-main-result .f-field-result .f-child1:after {
.f-fs-result .f-field-result .f-child1:after {
content: ": ";
}
.f-fs-result .f-field-check {
border: 0;
margin: 0;
width: 3rem;
overflow: hidden;
text-align: center;
@ -2352,22 +2358,26 @@ select {
}
@media screen and (min-width: 36rem) {
.f-wrap-main-result .f-field-result > dt,
.f-wrap-main-result .f-field-result > dd {
.f-fs-result .f-field-result > dt,
.f-fs-result .f-field-result > dd {
display: block;
}
.f-wrap-main-result .f-field-result .f-child1 {
.f-fs-result .f-field-result .f-child1 {
display: block;
font-weight: normal;
}
.f-wrap-main-result .f-field-result .f-child1:after {
.f-fs-result .f-field-result .f-child1:after {
content: "";
}
}
@media screen and (min-width: 50rem) {
.f-fs-stat {
display: flex;
}
.f-wrap-main-result {
display: flex;
}
@ -2379,7 +2389,8 @@ select {
justify-content: center;
}
.f-fs-result .f-field-result > dt {
.f-fs-result .f-field-result > dt,
.f-fs-result:first-of-type .f-field-check > dt {
display: block;
margin: 0;
width: 100%;
@ -2400,7 +2411,8 @@ select {
display: none;
}
.f-fs-result .f-field-result .f-child1 {
.f-fs-result .f-field-result .f-child1,
.f-fs-result .f-field-check .f-child1 {
font-weight: bold;
}
@ -2440,4 +2452,24 @@ select {
border-left: 0.0625rem dotted #AA7939;
}
.f-fs-result .f-field-ip {
width: 25%;
}
.f-fs-result .f-field-last-used {
width: 25%;
border-left: 0.0625rem dotted #AA7939;
text-align: center;
}
.f-fs-result .f-field-used-times {
width: 20%;
border-left: 0.0625rem dotted #AA7939;
text-align: center;
}
.f-fs-result .f-field-action {
width: 30%;
border-left: 0.0625rem dotted #AA7939;
}
}