ModelChangeDetector.php 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <?php
  2. namespace App\Services\History;
  3. use App\Models\Enums\ActionObjectType;
  4. use Illuminate\Database\Eloquent\Model;
  5. class ModelChangeDetector
  6. {
  7. public static function detector(ActionObjectType $objectType, Model $model): array
  8. {
  9. $detector = $objectType->detectorClassName();
  10. if (! $detector) {
  11. return [];
  12. }
  13. $fields = call_user_func([$detector, "fields"]);
  14. $diffFields = call_user_func([$detector, "diffFields"]);
  15. $arrayFields = call_user_func([$detector, "arrayFields"]);
  16. if (!$fields) {
  17. return [];
  18. }
  19. $items = [];
  20. foreach ($fields as $field) {
  21. if (! $model->isDirty($field) && ! in_array($field, $diffFields)) {
  22. continue;
  23. }
  24. if (in_array($field, $arrayFields)) {
  25. $items = array_merge($items, self::getArrayChange($model, $field));
  26. } else {
  27. $change = self::getChange($model, $field);
  28. if ($change['diff']) {
  29. $items[] = $change;
  30. }
  31. }
  32. }
  33. return $items;
  34. }
  35. public static function getChange(Model $model, $field): array
  36. {
  37. return [
  38. 'old' => is_array($model->getOriginal($field)) ? json_encode($model->getOriginal($field)) : $model->getOriginal($field),
  39. 'field' => $field,
  40. 'new' => is_array($model->$field) ? json_encode($model->$field) : $model->$field,
  41. 'diff' => text_diff($model->getOriginal($field) ?? '', $model->$field ?? '')
  42. ];
  43. }
  44. public static function getArrayChange(Model $model, $field): array
  45. {
  46. $items = [];
  47. $oldArr = $model->getOriginal($field);
  48. $newArr = $model->$field;
  49. foreach ($newArr as $field => $newValue) {
  50. $oldValue = $oldArr[$field] ?? null;
  51. $diff = text_diff($oldValue ?? '', $newValue ?? '');
  52. if (!$diff) {
  53. continue;
  54. }
  55. $items[] = [
  56. 'old' => is_array($oldValue) ? json_encode($oldValue, JSON_UNESCAPED_UNICODE) : $oldValue,
  57. 'field' => $field,
  58. 'new' => is_array($newValue) ? json_encode($newValue, JSON_UNESCAPED_UNICODE) : $newValue,
  59. 'diff' => $diff
  60. ];
  61. }
  62. return $items;
  63. }
  64. }