Folder reorganize 1
This commit is contained in:
172
includes/control-logger.php
Normal file
172
includes/control-logger.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php // phpcs:ignoreFile
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/db.php';
|
||||
|
||||
if (!function_exists('control_log_write')) {
|
||||
/**
|
||||
* Persist a control write audit entry into the configured log store.
|
||||
*
|
||||
* @param array<string, mixed> $entry
|
||||
*
|
||||
* @return array{success:bool, driver:?string, error:?string, path:?string}
|
||||
*/
|
||||
function control_log_write(array $entry): array
|
||||
{
|
||||
static $tableName;
|
||||
static $fallbackPath;
|
||||
/** @var array<string, array<int, string>> $columnsCache */
|
||||
static $columnsCache = [];
|
||||
|
||||
$result = [
|
||||
'success' => false,
|
||||
'driver' => null,
|
||||
'error' => null,
|
||||
'path' => null,
|
||||
];
|
||||
|
||||
$settings = include __DIR__ . '/../config/control-settings.php';
|
||||
|
||||
if ($tableName === null) {
|
||||
$configuredTable = $settings['log_table'] ?? null;
|
||||
|
||||
if (!is_string($configuredTable) || trim($configuredTable) === '') {
|
||||
$result['error'] = 'Control log table name is not configured.';
|
||||
error_log('Control write log insert failed: ' . $result['error']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$tableName = trim($configuredTable);
|
||||
}
|
||||
|
||||
if ($fallbackPath === null) {
|
||||
$configuredFallback = $settings['log_fallback_path'] ?? '';
|
||||
if (is_string($configuredFallback) && trim($configuredFallback) !== '') {
|
||||
$fallbackPath = $configuredFallback;
|
||||
} else {
|
||||
$fallbackPath = '';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$connection = controls_db_connect();
|
||||
$tableKey = $tableName;
|
||||
|
||||
if (!isset($columnsCache[$tableKey])) {
|
||||
$tableEscaped = $connection->real_escape_string($tableName);
|
||||
$columnsResult = $connection->query('SHOW COLUMNS FROM `' . $tableEscaped . '`');
|
||||
|
||||
if ($columnsResult === false) {
|
||||
throw new RuntimeException('Unable to determine columns for control write log table.');
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
while ($column = $columnsResult->fetch_assoc()) {
|
||||
if (isset($column['Field'])) {
|
||||
$columns[] = $column['Field'];
|
||||
}
|
||||
}
|
||||
|
||||
$columnsResult->free();
|
||||
$columnsCache[$tableKey] = $columns;
|
||||
}
|
||||
|
||||
$availableColumns = $columnsCache[$tableKey] ?? [];
|
||||
|
||||
if ($availableColumns === []) {
|
||||
throw new RuntimeException('No columns available on control write log table.');
|
||||
}
|
||||
|
||||
$insertData = [];
|
||||
foreach ($entry as $column => $value) {
|
||||
if (in_array($column, $availableColumns, true)) {
|
||||
$insertData[$column] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($insertData === []) {
|
||||
$result['error'] = 'None of the provided fields matched the log table columns.';
|
||||
error_log('Control write log insert skipped: ' . $result['error']);
|
||||
} else {
|
||||
$fields = [];
|
||||
$values = [];
|
||||
foreach ($insertData as $column => $value) {
|
||||
$fields[] = '`' . $connection->real_escape_string($column) . '`';
|
||||
|
||||
if ($value === null) {
|
||||
$values[] = 'NULL';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
$values[] = $value ? "'1'" : "'0'";
|
||||
continue;
|
||||
}
|
||||
|
||||
$values[] = "'" . $connection->real_escape_string((string) $value) . "'";
|
||||
}
|
||||
|
||||
$tableEscaped = $connection->real_escape_string($tableName);
|
||||
$sql = sprintf(
|
||||
'INSERT INTO `%s` (%s) VALUES (%s)',
|
||||
$tableEscaped,
|
||||
implode(', ', $fields),
|
||||
implode(', ', $values)
|
||||
);
|
||||
|
||||
$connection->query($sql);
|
||||
|
||||
$result['success'] = true;
|
||||
$result['driver'] = 'database';
|
||||
$result['error'] = null;
|
||||
return $result;
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
$result['error'] = $exception->getMessage();
|
||||
error_log('Control write log insert failed: ' . $exception->getMessage());
|
||||
}
|
||||
|
||||
if ($fallbackPath === '') {
|
||||
return $result;
|
||||
}
|
||||
|
||||
try {
|
||||
$directory = dirname($fallbackPath);
|
||||
if ($directory !== '' && !is_dir($directory)) {
|
||||
if (!mkdir($directory, 0775, true) && !is_dir($directory)) {
|
||||
throw new RuntimeException('Unable to create fallback log directory: ' . $directory);
|
||||
}
|
||||
}
|
||||
|
||||
$record = [
|
||||
'timestamp' => gmdate('c'),
|
||||
'entry' => $entry,
|
||||
'error' => $result['error'],
|
||||
];
|
||||
|
||||
$json = json_encode($record, JSON_THROW_ON_ERROR);
|
||||
file_put_contents($fallbackPath, $json . PHP_EOL, FILE_APPEND | LOCK_EX);
|
||||
|
||||
$result['success'] = true;
|
||||
$result['driver'] = 'file';
|
||||
$result['path'] = $fallbackPath;
|
||||
|
||||
error_log('Control write log stored in fallback file: ' . $fallbackPath);
|
||||
} catch (Throwable $fallbackException) {
|
||||
$result['driver'] = 'none';
|
||||
$result['path'] = null;
|
||||
|
||||
$fallbackMessage = $fallbackException->getMessage();
|
||||
if ($result['error'] !== null) {
|
||||
$result['error'] .= '; ' . $fallbackMessage;
|
||||
} else {
|
||||
$result['error'] = $fallbackMessage;
|
||||
}
|
||||
|
||||
error_log('Control write log fallback failed: ' . $fallbackMessage);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user