ModelChangeDetector.php 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. if (!is_array($newArr) || !is_object($newArr)) {
  50. return [];
  51. }
  52. foreach ($newArr as $field => $newValue) {
  53. $oldValue = $oldArr[$field] ?? null;
  54. $diff = text_diff($oldValue ?? '', $newValue ?? '');
  55. if (!$diff) {
  56. continue;
  57. }
  58. $items[] = [
  59. 'old' => is_array($oldValue) ? json_encode($oldValue, JSON_UNESCAPED_UNICODE) : $oldValue,
  60. 'field' => $field,
  61. 'new' => is_array($newValue) ? json_encode($newValue, JSON_UNESCAPED_UNICODE) : $newValue,
  62. 'diff' => $diff
  63. ];
  64. }
  65. return $items;
  66. }
  67. }