1 | <?php |
||
10 | trait DetectsChanges |
||
11 | { |
||
12 | protected $oldAttributes = []; |
||
13 | |||
14 | 216 | protected static function bootDetectsChanges() |
|
27 | |||
28 | 88 | public function attributesToBeLogged(): array |
|
29 | { |
||
30 | 88 | $attributes = []; |
|
31 | |||
32 | 88 | if (isset(static::$logFillable) && static::$logFillable) { |
|
33 | $attributes = array_merge($attributes, $this->getFillable()); |
||
34 | } |
||
35 | |||
36 | 88 | if ($this->shouldLogUnguarded()) { |
|
37 | $attributes = array_merge($attributes, array_diff(array_keys($this->getAttributes()), $this->getGuarded())); |
||
38 | } |
||
39 | |||
40 | 88 | if (isset(static::$logAttributes) && is_array(static::$logAttributes)) { |
|
41 | 64 | $attributes = array_merge($attributes, array_diff(static::$logAttributes, ['*'])); |
|
42 | |||
43 | 64 | if (in_array('*', static::$logAttributes)) { |
|
44 | 12 | $attributes = array_merge($attributes, array_keys($this->getAttributes())); |
|
45 | } |
||
46 | } |
||
47 | |||
48 | 88 | if (isset(static::$logAttributesToIgnore) && is_array(static::$logAttributesToIgnore)) { |
|
49 | $attributes = array_diff($attributes, static::$logAttributesToIgnore); |
||
50 | } |
||
51 | |||
52 | 88 | return $attributes; |
|
53 | } |
||
54 | |||
55 | public function shouldLogOnlyDirty(): bool |
||
56 | { |
||
57 | if (! isset(static::$logOnlyDirty)) { |
||
58 | return false; |
||
59 | } |
||
60 | |||
61 | return static::$logOnlyDirty; |
||
62 | } |
||
63 | |||
64 | 88 | public function shouldLogUnguarded(): bool |
|
65 | { |
||
66 | 88 | if (! isset(static::$logUnguarded)) { |
|
67 | 88 | return false; |
|
68 | } |
||
69 | |||
70 | if (! static::$logUnguarded) { |
||
71 | return false; |
||
72 | } |
||
73 | |||
74 | if (in_array('*', $this->getGuarded())) { |
||
75 | return false; |
||
76 | } |
||
77 | |||
78 | return true; |
||
79 | } |
||
80 | |||
81 | public function attributeValuesToBeLogged(string $processingEvent): array |
||
82 | { |
||
83 | if (! count($this->attributesToBeLogged())) { |
||
84 | return []; |
||
85 | } |
||
86 | |||
87 | $properties['attributes'] = static::logChanges( |
||
88 | $this->exists |
||
89 | ? $this->fresh() ?? $this |
||
90 | : $this |
||
91 | ); |
||
92 | |||
93 | if (static::eventsToBeRecorded()->contains('updated') && $processingEvent == 'updated') { |
||
94 | $nullProperties = array_fill_keys(array_keys($properties['attributes']), null); |
||
95 | |||
96 | $properties['old'] = array_merge($nullProperties, $this->oldAttributes); |
||
97 | |||
98 | $this->oldAttributes = []; |
||
99 | } |
||
100 | |||
101 | if ($this->shouldLogOnlyDirty() && isset($properties['old'])) { |
||
102 | $properties['attributes'] = array_udiff_assoc( |
||
103 | $properties['attributes'], |
||
104 | $properties['old'], |
||
105 | function ($new, $old) { |
||
106 | if ($old === null || $new === null) { |
||
107 | return $new === $old ? 0 : 1; |
||
108 | } |
||
109 | |||
110 | return $new <=> $old; |
||
111 | } |
||
112 | ); |
||
113 | $properties['old'] = collect($properties['old']) |
||
114 | ->only(array_keys($properties['attributes'])) |
||
115 | ->all(); |
||
116 | } |
||
117 | |||
118 | return $properties; |
||
119 | } |
||
120 | |||
121 | 88 | public static function logChanges(Model $model): array |
|
151 | |||
152 | 20 | protected static function getRelatedModelAttributeValue(Model $model, string $attribute): array |
|
166 | |||
167 | 16 | protected static function getModelAttributeJsonValue(Model $model, string $attribute) |
|
175 | } |
||
176 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.