mirror of
https://github.com/openvk/openvk
synced 2024-11-14 19:19:14 +03:00
Совместимость с новыми логами
This commit is contained in:
parent
1ef08ae1b7
commit
34d2e32f3c
6 changed files with 10 additions and 328 deletions
|
@ -1,190 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use openvk\Web\Models\Repositories\GeodbCities;
|
||||
use openvk\Web\Models\Repositories\GeodbCountries;
|
||||
use openvk\Web\Models\Repositories\GeodbEducation;
|
||||
use openvk\Web\Models\Repositories\GeodbSpecializations;
|
||||
use openvk\Web\Models\Repositories\Users;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Util\DateTime;
|
||||
|
||||
class Log extends RowModel
|
||||
{
|
||||
protected $tableName = "logs";
|
||||
|
||||
function getId(): int
|
||||
{
|
||||
return (int) $this->getRecord()->id;
|
||||
}
|
||||
|
||||
function getUser(): ?User
|
||||
{
|
||||
return (new Users)->get((int) $this->getRecord()->user);
|
||||
}
|
||||
|
||||
function getObjectTable(): string
|
||||
{
|
||||
return $this->getRecord()->object_table;
|
||||
}
|
||||
|
||||
function getObjectId(): int
|
||||
{
|
||||
return $this->getRecord()->object_id;
|
||||
}
|
||||
|
||||
function getObject()
|
||||
{
|
||||
$model = $this->getRecord()->object_model;
|
||||
return new $model(DatabaseConnection::i()->getContext()->table($this->getObjectTable())->get($this->getObjectId()));
|
||||
}
|
||||
|
||||
function getTypeRaw(): int
|
||||
{
|
||||
return $this->getRecord()->type;
|
||||
}
|
||||
|
||||
function getType(): string
|
||||
{
|
||||
return ["добавил", "отредактировал", "удалил", "восстановил"][$this->getTypeRaw()];
|
||||
}
|
||||
|
||||
function getTypeNom(): string
|
||||
{
|
||||
return ["Создание", "Редактирование", "Удаление", "Восстановление"][$this->getTypeRaw()];
|
||||
}
|
||||
|
||||
function getObjectType(): string
|
||||
{
|
||||
return [
|
||||
"albums" => "Альбом",
|
||||
"groups" => "Сообщество",
|
||||
"profiles" => "Профиль",
|
||||
"comments" => "Комментарий",
|
||||
"ip" => "IP-адрес",
|
||||
"posts" => "Запись",
|
||||
"tickets" => "Вопрос",
|
||||
"tickets_comments" => "Комментарий к тикету",
|
||||
][$this->getRecord()->object_table] ?? $this->getRecord()->object_model;
|
||||
}
|
||||
|
||||
function getObjectName(): string
|
||||
{
|
||||
$object = $this->getObject();
|
||||
if (method_exists($object, 'getCanonicalName'))
|
||||
return $object->getCanonicalName();
|
||||
else return "[#" . $this->getObjectId() . "] " . $this->getObjectType();
|
||||
}
|
||||
|
||||
function getLogsText(): string
|
||||
{
|
||||
return $this->getRecord()->logs_text;
|
||||
}
|
||||
|
||||
function getObjectURL(): string
|
||||
{
|
||||
$object = $this->getObject();
|
||||
if (method_exists($object, "getURL") && $this->getObjectTable() !== "videos")
|
||||
return $this->getObject()->getURL();
|
||||
else
|
||||
return "#";
|
||||
}
|
||||
|
||||
function getObjectAvatar(): ?string
|
||||
{
|
||||
$object = $this->getObject();
|
||||
if (method_exists($object, 'getAvatarURL'))
|
||||
return $object->getAvatarURL("normal");
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
function getOldValue(): ?array
|
||||
{
|
||||
return (array) json_decode($this->getRecord()->xdiff_old, true, JSON_UNESCAPED_UNICODE) ?? null;
|
||||
}
|
||||
|
||||
function getNewValue(): ?array
|
||||
{
|
||||
return (array) json_decode($this->getRecord()->xdiff_new, true, JSON_UNESCAPED_UNICODE) ?? null;
|
||||
}
|
||||
|
||||
function getTime(): DateTime
|
||||
{
|
||||
return new DateTime($this->getRecord()->ts);
|
||||
}
|
||||
|
||||
function diff($old, $new): array
|
||||
{
|
||||
$matrix = array();
|
||||
$maxlen = 0;
|
||||
foreach ($old as $oindex => $ovalue) {
|
||||
$nkeys = array_keys($new, $ovalue);
|
||||
foreach ($nkeys as $nindex) {
|
||||
$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
|
||||
$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
|
||||
if ($matrix[$oindex][$nindex] > $maxlen) {
|
||||
$maxlen = $matrix[$oindex][$nindex];
|
||||
$omax = $oindex + 1 - $maxlen;
|
||||
$nmax = $nindex + 1 - $maxlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($maxlen == 0) return array(array('d' => $old, 'i' => $new));
|
||||
return array_merge(
|
||||
$this->diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
|
||||
array_slice($new, $nmax, $maxlen),
|
||||
$this->diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
|
||||
}
|
||||
|
||||
function htmlDiff($old, $new): string
|
||||
{
|
||||
$ret = '';
|
||||
$diff = $this->diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new));
|
||||
foreach ($diff as $k) {
|
||||
if (is_array($k))
|
||||
$ret .= (!empty($k['d']) ? "<del>" . implode(' ', $k['d']) . "</del> " : '') .
|
||||
(!empty($k['i']) ? "<ins>" . implode(' ', $k['i']) . "</ins> " : '');
|
||||
else $ret .= $k . ' ';
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function getChanges(): array
|
||||
{
|
||||
$result = $this->getOldValue();
|
||||
$_changes = [];
|
||||
|
||||
if ($this->getTypeRaw() === 1) { // edit
|
||||
$changes = $this->getNewValue();
|
||||
|
||||
foreach ($changes as $field => $value) {
|
||||
$new_value = xdiff_string_patch((string) $result[$field], (string) $value);
|
||||
$_changes[$field] = [
|
||||
"field" => $field,
|
||||
"old_value" => $result[$field],
|
||||
"new_value" => strlen($new_value) > 0 ? $new_value : "(empty)",
|
||||
"ts" => $this->getTime(),
|
||||
"diff" => $this->htmlDiff((string) $result[$field], (string) $new_value)
|
||||
];
|
||||
}
|
||||
} else if ($this->getTypeRaw() === 0) { // create
|
||||
foreach ($result as $field => $value) {
|
||||
$_changes[$field] = [
|
||||
"field" => $field,
|
||||
"old_value" => $value,
|
||||
"ts" => $this->getTime()
|
||||
];
|
||||
}
|
||||
} else if ($this->getTypeRaw() === 2) { // delete
|
||||
$_changes[] = [
|
||||
"field" => "deleted",
|
||||
"old_value" => 0,
|
||||
"new_value" => 1,
|
||||
"ts" => $this->getTime(),
|
||||
"diff" => $this->htmlDiff("0", "1")
|
||||
];
|
||||
}
|
||||
|
||||
return $_changes;
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Repositories;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use Nette\Database\Table\ActiveRow;
|
||||
use openvk\Web\Models\Entities\Country;
|
||||
use openvk\Web\Models\Entities\Editor;
|
||||
use openvk\Web\Models\Entities\Log;
|
||||
use openvk\Web\Models\Entities\User;
|
||||
|
||||
class Logs
|
||||
{
|
||||
private $context;
|
||||
private $logs;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->context = DatabaseConnection::i()->getContext();
|
||||
$this->logs = $this->context->table("logs");
|
||||
}
|
||||
|
||||
private function toLog(?ActiveRow $ar): ?Log
|
||||
{
|
||||
return is_null($ar) ? NULL : new Log($ar);
|
||||
}
|
||||
|
||||
function get(int $id): ?Log
|
||||
{
|
||||
return $this->toLog($this->logs->get($id));
|
||||
}
|
||||
|
||||
function create(int $user, string $table, string $model, int $type, $object, $changes, ?string $ip = NULL, ?string $useragent = NULL): void
|
||||
{
|
||||
if (OPENVK_ROOT_CONF["openvk"]["preferences"]["logs"] === true) {
|
||||
$fobject = (is_array($object) ? $object : $object->unwrap());
|
||||
$nobject = [];
|
||||
$_changes = [];
|
||||
|
||||
if ($type === 1) {
|
||||
foreach ($changes as $field => $value) {
|
||||
$nobject[$field] = $fobject[$field];
|
||||
}
|
||||
|
||||
foreach (array_diff_assoc($nobject, $changes) as $field => $value) {
|
||||
if (str_starts_with($field, "rate_limit")) continue;
|
||||
if ($field === "online") continue;
|
||||
$_changes[$field] = xdiff_string_diff((string)$nobject[$field], (string)$changes[$field]);
|
||||
}
|
||||
|
||||
if (count($_changes) === 0) return;
|
||||
} else if ($type === 0) { // if new
|
||||
$nobject = $fobject;
|
||||
foreach ($fobject as $field => $value) {
|
||||
$_changes[$field] = xdiff_string_diff("", (string)$value);
|
||||
}
|
||||
} else if ($type === 2 || $type === 3) { // if deleting or restoring
|
||||
$_changes["deleted"] = (int)($type === 2);
|
||||
}
|
||||
|
||||
$log = new Log;
|
||||
$log->setUser($user);
|
||||
$log->setType($type);
|
||||
$log->setObject_Table($table);
|
||||
$log->setObject_Model($model);
|
||||
$log->setObject_Id(is_array($object) ? $object["id"] : $object->getId());
|
||||
$log->setXdiff_Old(json_encode($nobject));
|
||||
$log->setXdiff_New(json_encode($_changes));
|
||||
$log->setTs(time());
|
||||
$log->setIp($ip ?? CurrentUser::i()->getIP());
|
||||
$log->setUserAgent($useragent ?? CurrentUser::i()->getUserAgent());
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
|
||||
function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$query = "%$query%";
|
||||
$result = $this->logs->where("id LIKE ? OR object_table LIKE ?", $query, $query);
|
||||
|
||||
return new Util\EntityStream("Log", $result->order($sort));
|
||||
}
|
||||
|
||||
function search($filter): \Traversable
|
||||
{
|
||||
foreach ($this->logs->where($filter)->order("id DESC") as $log)
|
||||
yield new Log($log);
|
||||
}
|
||||
|
||||
function getTypes(): array
|
||||
{
|
||||
$types = [];
|
||||
foreach ($this->context->query("SELECT DISTINCT(`object_model`) AS `object_model` FROM `logs`")->fetchAll() as $type)
|
||||
$types[] = str_replace("openvk\\Web\\Models\\Entities\\", "", $type->object_model);
|
||||
|
||||
return $types;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use Chandler\Database\Log;
|
||||
use Chandler\Database\Logs;
|
||||
use openvk\Web\Models\Entities\{Voucher, Gift, GiftCategory, User, BannedLink};
|
||||
use openvk\Web\Models\Repositories\{ChandlerGroups, ChandlerUsers, Logs, Users, Clubs, Vouchers, Gifts, BannedLinks};
|
||||
use openvk\Web\Models\Repositories\{Bans, ChandlerGroups, ChandlerUsers, Photos, Posts, Users, Clubs, Videos, Vouchers, Gifts, BannedLinks};
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
final class AdminPresenter extends OpenVKPresenter
|
||||
|
@ -14,7 +16,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
private $chandlerGroups;
|
||||
private $logs;
|
||||
|
||||
function __construct(Users $users, Clubs $clubs, Vouchers $vouchers, Gifts $gifts, BannedLinks $bannedLinks, ChandlerGroups $chandlerGroups, Logs $logs)
|
||||
function __construct(Users $users, Clubs $clubs, Vouchers $vouchers, Gifts $gifts, BannedLinks $bannedLinks, ChandlerGroups $chandlerGroups)
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->clubs = $clubs;
|
||||
|
@ -22,7 +24,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$this->gifts = $gifts;
|
||||
$this->bannedLinks = $bannedLinks;
|
||||
$this->chandlerGroups = $chandlerGroups;
|
||||
$this->logs = $logs;
|
||||
$this->logs = DatabaseConnection::i()->getContext()->table("ChandlerLogs");
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
@ -568,7 +570,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$this->template->type = $type;
|
||||
}
|
||||
if ($this->queryParam("uid")) {
|
||||
$user = (int) $this->queryParam("uid");
|
||||
$user = $this->queryParam("uid");
|
||||
$filter["user"] = $user;
|
||||
$this->template->user = $user;
|
||||
}
|
||||
|
@ -578,17 +580,12 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$this->template->obj_id = $obj_id;
|
||||
}
|
||||
if ($this->queryParam("obj_type") !== NULL && $this->queryParam("obj_type") !== "any") {
|
||||
$obj_type = "openvk\\Web\\Models\\Entities\\" . $this->queryParam("obj_type");
|
||||
$obj_type = CHANDLER_ROOT_CONF["preferences"]["logs"]["entitiesNamespace"] . $this->queryParam("obj_type");
|
||||
$filter["object_model"] = $obj_type;
|
||||
$this->template->obj_type = $obj_type;
|
||||
}
|
||||
|
||||
if (count($filter) === 0) {
|
||||
$this->template->logs = $this->searchResults($this->logs, $this->template->count);
|
||||
} else {
|
||||
$this->template->logs = $this->logs->search($filter);
|
||||
}
|
||||
|
||||
$this->template->logs = (new Logs)->search($filter);
|
||||
$this->template->object_types = (new Logs)->getTypes();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
{var $logs = iterator_to_array($logs)}
|
||||
{var $amount = sizeof($logs)}
|
||||
|
||||
<style>
|
||||
|
@ -27,7 +26,7 @@
|
|||
<option value="3" n:attr="selected => $type === 3">Восстановление</option>
|
||||
</select>
|
||||
<input class="text medium-field" type="number" id="id" name="id" placeholder="ID записи" n:attr="value => $id"/>
|
||||
<input class="text medium-field" type="number" id="uid" name="uid" placeholder="ID пользователя" n:attr="value => $user"/>
|
||||
<input class="text medium-field" type="text" id="uid" name="uid" placeholder="UUID пользователя" n:attr="value => $user"/>
|
||||
</div>
|
||||
<div style="margin: 8px 0;" />
|
||||
<div>
|
||||
|
@ -51,16 +50,10 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr n:foreach="$logs as $log">
|
||||
<td>{$log->getId()}</td>
|
||||
<td>
|
||||
<span n:if="$log->getUser()->getAvatarURL()" class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$log->getUser()->getAvatarURL()}" alt="{$log->getUser()->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
||||
</span>
|
||||
</span>
|
||||
<a href="{$log->getUser()->getURL()}">{$log->getUser()->getCanonicalName()}</a>
|
||||
<a href="/admin/chandler/user/{$log->getUser()}" target="_blank">{$log->getUser()}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span n:if="$log->getObjectAvatar()" class="aui-avatar aui-avatar-xsmall">
|
||||
|
|
|
@ -49,4 +49,3 @@ services:
|
|||
- openvk\Web\Models\Repositories\BannedLinks
|
||||
- openvk\Web\Models\Repositories\ChandlerGroups
|
||||
- openvk\Web\Presenters\MaintenancePresenter
|
||||
- openvk\Web\Models\Repositories\Logs
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
CREATE TABLE `logs`
|
||||
(
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`user` bigint(20) UNSIGNED NOT NULL,
|
||||
`type` int(11) NOT NULL,
|
||||
`object_table` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`object_model` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`object_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`xdiff_old` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`xdiff_new` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`ts` bigint(20) NOT NULL,
|
||||
`ip` tinytext NOT NULL,
|
||||
`useragent` longtext NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
ALTER TABLE `logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `logs`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
COMMIT;
|
Loading…
Reference in a new issue