<?php
class SubPage
{
const OP_LIST = ['*', '=', '!=', '<', '<=', '>', '>=', 'regex'];
public static function doPreprocess()
{
if (Request::isPost()) {
User::assertPermission('filter.rules.edit');
$action = Request::post('action');
if ($action === 'save-filter') {
self::saveRule();
} elseif ($action === 'delete-filter') {
self::deleteRule();
} else {
Message::addError('main.invalid-action', $action);
}
Util::redirect('?do=eventlog&show=rules');
}
}
private static function saveRule()
{
User::assertPermission('filter.rules.edit');
$id = Request::post('id', Request::REQUIRED, 'int');
$type = Request::post('type', Request::REQUIRED, 'string');
$title = Request::post('title', Request::REQUIRED, 'string');
$message = Request::post('message', Request::REQUIRED, 'string');
$transports = Request::post('transports', [], 'array');
$filters = Request::post('filter', Request::REQUIRED, 'array');
$filters = array_filter($filters, function ($item) {
return is_array($item) && !empty($item['path']) && !empty($item['op']);
});
foreach ($filters as $index => &$item) {
$item['index'] = $index;
}
unset($item);
if (empty($filters)) {
Message::addError('no-valid-filters');
Util::redirect('?do=eventlog&show=rules');
}
if ($id === 0) {
$id = null;
}
$data = [
'id' => $id,
'type' => $type,
'title' => $title,
'description' => Request::post('description', '', 'string'),
'data' => json_encode(['list' => array_values($filters)]),
'subject' => Request::post('subject', '', 'string'),
'message' => $message,
];
if ($id === null) {
// NEW
Database::exec("INSERT INTO notification_rule (ruleid, title, description, type, datafilter, subject, message)
VALUES (:id, :title, :description, :type, :data, :subject, :message)", $data);
$id = Database::lastInsertId();
} else {
Database::exec("UPDATE notification_rule SET type = :type, title = :title, description = :description, datafilter = :data,
subject = :subject, message = :message
WHERE ruleid = :id", $data);
}
if (empty($transports)) {
Database::exec("DELETE FROM notification_rule_x_transport WHERE ruleid = :id", ['id' => $id]);
} else {
Database::exec("DELETE FROM notification_rule_x_transport
WHERE ruleid = :id AND transportid NOT IN (:transports)",
['id' => $id, 'transports' => $transports]);
Database::exec("INSERT IGNORE INTO notification_rule_x_transport (ruleid, transportid)
VALUES :list", ['list' => array_map(function ($i) use ($id) { return [$id, $i]; }, $transports)]);
}
Message::addSuccess("event-rule-saved", $id);
Util::redirect('?do=eventlog&show=rules');
}
private static function deleteRule()
{
User::assertPermission('filter.rules.edit');
$id = Request::post('id', Request::REQUIRED, 'int');
Database::exec("DELETE FROM notification_rule WHERE ruleid = :id", ['id' => $id]);
}
/*
*
*/
public static function doRender()
{
User::assertPermission('filter.rules.view');
$id = Request::get('id', null, 'int');
if ($id !== null) {
self::showRuleEditor($id);
} else {
// LIST
$data = [];
$data['filters'] = Database::queryAll('SELECT ruleid, type, title, datafilter,
Count(transportid) AS useCount
FROM notification_rule
LEFT JOIN notification_rule_x_transport sfxb USING (ruleid)
GROUP BY ruleid, title
ORDER BY title, ruleid');
Permission::addGlobalTags($data['perms'], null, ['filter.rules.edit']);
Render::addTemplate('page-filters-rules', $data);
}
}
/**
* @param int $id Rule to edit. If id is 0, a new rule will be created.
*/
private static function showRuleEditor(int $id)
{
// EDIT
User::assertPermission('filter.rules.edit');
$filterIdx = 0;
$knownIdxList = [];
if ($id !== 0) {
$data = Database::queryFirst('SELECT ruleid, title, description, type, datafilter, subject, message
FROM notification_rule WHERE ruleid = :id', ['id' => $id]);
if ($data === false) {
Message::addError('invalid-rule-id', $id);
Util::redirect('?do=eventlog&show=rules');
}
if (Request::get('copy', false, 'bool')) {
$data['ruleid'] = 0;
$data['title'] = '';
}
$list = json_decode($data['datafilter'], true);
if (!is_array($list['list'])) {
$list['list'] = [];
}
foreach ($list['list'] as $item) {
if (isset($item['index'])) {
$knownIdxList[] = $item['index'];
}
}
foreach ($list['list'] as &$item) {
if (!isset($item['index'])) {
while (in_array($filterIdx, $knownIdxList)) {
$filterIdx++;
}
$item['index'] = $filterIdx++;
}
$item['operators'] = [];
foreach (self::OP_LIST as $op) {
$item['operators'][] = [
'name' => $op,
'selected' => ($op === $item['op']) ? 'selected' : '',
];
}
}
$data['filter'] = $list['list'];
} else {
// New entry
$data = ['filter' => [], 'ruleid' => 0];
}
// Add suggestions for type
$data['types'] = Database::queryColumnArray("SELECT DISTINCT type
FROM notification_sample
ORDER BY type");
//
Module::isAvailable('bootstrap_multiselect');
$data['transports'] = Database::queryAll("SELECT nb.transportid, nb.title,
IF(sfxb.ruleid IS NULL, '', 'selected') AS selected
FROM notification_backend nb
LEFT JOIN notification_rule_x_transport sfxb ON (sfxb.transportid = nb.transportid AND sfxb.ruleid = :id)",
['id' => $id]);
if (Module::isAvailable('statistics')) {
// Filter keys to suggest for events with machineuuid in data
$data['machine_keys'] = array_keys(FilterRuleProcessor::HW_QUERIES);
}
// Add a few empty rows at the bottom
for ($i = 0; $i < 8; ++$i) {
while (in_array($filterIdx, $knownIdxList)) {
$filterIdx++;
}
$data['filter'][] = [
'index' => $filterIdx++,
'operators' => array_map(function ($item) { return ['name' => $item]; }, self::OP_LIST),
];
}
Render::addTemplate('page-filters-edit-rule', $data);
}
}