LocalizedAuditService.php 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. <?php
  2. namespace App\Services;
  3. use App\Support\LocalizedContent;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Validator;
  6. use Illuminate\Validation\Rule;
  7. class LocalizedAuditService
  8. {
  9. public static function listing(string $type, array $input, ?callable $scope = null): array
  10. {
  11. $params = Validator::make($input, [
  12. 'page' => ['nullable', 'integer', 'min:1'], 'limit' => ['nullable', 'integer', 'min:1', 'max:200'],
  13. 'language' => ['nullable', Rule::in(array_keys(LocalizedContent::LANGUAGES))],
  14. 'operator_name' => ['nullable', 'string', 'max:100'], 'resource_id' => ['nullable', 'integer', 'min:1'],
  15. 'start_date' => ['nullable', 'required_with:end_date', 'date_format:Y-m-d'],
  16. 'end_date' => ['nullable', 'required_with:start_date', 'date_format:Y-m-d', 'after_or_equal:start_date'],
  17. ])->validate();
  18. $query = DB::table('operation_audits as a')->where('a.resource_type', $type);
  19. if ($scope) $scope($query);
  20. if (isset($params['operator_name']) && $params['operator_name'] !== '') $query->where('a.operator_name', 'like', '%' . $params['operator_name'] . '%');
  21. if (!empty($params['resource_id'])) $query->where('a.resource_id', $params['resource_id']);
  22. if (!empty($params['start_date'])) $query->where('a.created_at', '>=', $params['start_date'] . ' 00:00:00')->where('a.created_at', '<=', $params['end_date'] . ' 23:59:59');
  23. if (!empty($params['language'])) {
  24. $language = $params['language'];
  25. $query->where(function ($q) use ($language) {
  26. $q->whereNotNull('a.changes->before->translations->' . $language)->orWhereNotNull('a.changes->after->translations->' . $language);
  27. });
  28. }
  29. $total = (clone $query)->count();
  30. $rows = $query->select('a.*')->orderByDesc('a.created_at')->orderByDesc('a.id')
  31. ->forPage((int) ($params['page'] ?? 1), (int) ($params['limit'] ?? 20))->get();
  32. $items = [];
  33. foreach ($rows as $row) {
  34. $change = json_decode($row->changes, true, 512, JSON_THROW_ON_ERROR);
  35. $before = $change['before'] ?? []; $after = $change['after'] ?? [];
  36. $translations = array_replace($before['translations'] ?? [], $after['translations'] ?? []);
  37. $titles = array_map(fn ($block) => $block['title'], $translations);
  38. $old = []; $new = [];
  39. foreach (array_unique(array_merge(array_keys($before), array_keys($after))) as $field) {
  40. if (in_array($field, ['id', 'created_at', 'updated_at', 'request_hash', 'request_id'], true)) continue;
  41. $a = $before[$field] ?? null; $b = $after[$field] ?? null;
  42. if ($field === 'translations' && !empty($params['language'])) {
  43. $a = isset($a[$params['language']]) ? [$params['language'] => $a[$params['language']]] : null;
  44. $b = isset($b[$params['language']]) ? [$params['language'] => $b[$params['language']]] : null;
  45. }
  46. if ($a !== $b) { $old[$field] = $a; $new[$field] = $b; }
  47. }
  48. $recipientType = $after['recipient_type'] ?? $before['recipient_type'] ?? 'all_users';
  49. $items[] = ['id' => (int) $row->id, 'resource_id' => (int) $row->resource_id,
  50. 'created_at' => $row->created_at, 'operator_name' => $row->operator_name, 'action' => $row->action,
  51. 'languages' => array_keys($translations), 'titles' => (object) $titles,
  52. 'recipient_type' => $recipientType,
  53. 'recipient_label' => $type === 'announcement' ? '所有人' : (SiteMessageService::TARGETS[$recipientType] ?? ''),
  54. 'old_values' => (object) $old, 'new_values' => (object) $new];
  55. }
  56. return ['total' => $total, 'data' => $items];
  57. }
  58. }