Files

150 lines
4.1 KiB
PHP

<?php
namespace App\Services\System;
use Illuminate\Support\Str;
class ActivityFormatter
{
/**
* Get a friendly name for the model.
*/
public static function getFriendlyModelName(?string $model): string
{
if (! $model) {
return 'System';
}
$className = class_basename($model);
// Custom mapping for specific models
$mapping = [
'SystemSetting' => 'System Config',
'User' => 'User Profile',
'Role' => 'Access Role',
'Permission' => 'Access Permission',
'MobileSetting' => 'Mobile Config',
];
return $mapping[$className] ?? Str::headline($className);
}
/**
* Get badge class for the event.
*/
public static function getEventBadgeClass(string $event): string
{
return match (strtolower($event)) {
'created' => 'text-bg-success',
'updated' => 'text-bg-warning',
'deleted' => 'text-bg-danger',
'restored' => 'text-bg-info',
'login', 'login_attempt' => 'text-bg-info',
'logout' => 'text-bg-secondary',
'password_changed', 'password reset' => 'text-bg-primary',
default => 'text-bg-theme-1',
};
}
/**
* Get icon for the event.
*/
public static function getEventIcon(string $event): string
{
return match (strtolower($event)) {
'created' => 'bi-plus-circle',
'updated' => 'bi-pencil-square',
'deleted' => 'bi-trash',
'restored' => 'bi-arrow-counterclockwise',
'login', 'login_attempt' => 'bi-box-arrow-in-right',
'logout' => 'bi-box-arrow-right',
'password_changed', 'password reset' => 'bi-key',
default => 'bi-info-circle',
};
}
/**
* Formats the changes between old and new properties.
*/
public static function formatChanges(array $properties): array
{
$old = $properties['old'] ?? [];
$new = $properties['attributes'] ?? [];
$changes = [];
// If it's a "created" event, show all attributes
if (empty($old) && ! empty($new)) {
foreach ($new as $key => $value) {
if (self::isSensitive($key)) {
continue;
}
$changes[] = [
'field' => Str::headline($key),
'old' => null,
'new' => self::formatValue($value),
];
}
return $changes;
}
// For updates, show only changed fields
foreach ($new as $key => $value) {
if (self::isSensitive($key)) {
continue;
}
$oldValue = $old[$key] ?? null;
// Loose comparison to handle type juggling from DB
if ($oldValue != $value) {
$changes[] = [
'field' => Str::headline($key),
'old' => self::formatValue($oldValue),
'new' => self::formatValue($value),
];
}
}
return $changes;
}
private static function isSensitive(string $key): bool
{
$sensitive = ['password', 'remember_token', 'secret', 'key', 'token', '2fa_secret'];
foreach ($sensitive as $s) {
if (str_contains(strtolower($key), $s)) {
return true;
}
}
return false;
}
private static function formatValue(mixed $value): string
{
if (is_null($value)) {
return 'NULL';
}
if (is_bool($value)) {
return $value ? 'TRUE' : 'FALSE';
}
if (is_array($value) || is_object($value)) {
return json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
if ($value === '') {
return '[empty]';
}
// Truncate long values but keep it readable
if (is_string($value) && strlen($value) > 200) {
return substr($value, 0, 197).'...';
}
return (string) $value;
}
}