Passed
Push — master ( 3a5738...0534b0 )
by Quetzy
03:08
created

Audit::user()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * This file is part of the Laravel Auditing package.
4
 *
5
 * @author     Antério Vieira <[email protected]>
6
 * @author     Quetzy Garcia  <[email protected]>
7
 * @author     Raphael França <[email protected]>
8
 * @copyright  2015-2018
9
 *
10
 * For the full copyright and license information,
11
 * please view the LICENSE.md file that was distributed
12
 * with this source code.
13
 */
14
15
namespace OwenIt\Auditing;
16
17
use DateTimeInterface;
18
use Illuminate\Database\Eloquent\Model;
19
use Illuminate\Support\Facades\Config;
20
use OwenIt\Auditing\Contracts\AttributeEncoder;
21
22
trait Audit
23
{
24
    /**
25
     * Audit data.
26
     *
27
     * @var array
28
     */
29
    protected $data = [];
30
31
    /**
32
     * The Audit attributes that belong to the metadata.
33
     *
34
     * @var array
35
     */
36
    protected $metadata = [];
37
38
    /**
39
     * The Auditable attributes that were modified.
40
     *
41
     * @var array
42
     */
43
    protected $modified = [];
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 144
    public function getConnectionName()
49
    {
50 144
        return Config::get('audit.drivers.database.connection');
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 144
    public function getTable(): string
57
    {
58 144
        return Config::get('audit.drivers.database.table', parent::getTable());
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 48
    public function resolveData(): array
65
    {
66 48
        $morphPrefix = Config::get('audit.user.morph_prefix', 'user');
67
68
        // Metadata
69 48
        $this->data = [
70 48
            'audit_id'         => $this->id,
71 48
            'audit_event'      => $this->event,
72 48
            'audit_url'        => $this->url,
73 48
            'audit_ip_address' => $this->ip_address,
74 48
            'audit_user_agent' => $this->user_agent,
75 48
            'audit_tags'       => $this->tags,
76 48
            'audit_created_at' => $this->serializeDate($this->created_at),
0 ignored issues
show
Bug introduced by
It seems like serializeDate() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

76
            'audit_created_at' => $this->/** @scrutinizer ignore-call */ serializeDate($this->created_at),
Loading history...
77 48
            'audit_updated_at' => $this->serializeDate($this->updated_at),
78 48
            'user_id'          => $this->getAttribute($morphPrefix.'_id'),
0 ignored issues
show
Bug introduced by
It seems like getAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
            'user_id'          => $this->/** @scrutinizer ignore-call */ getAttribute($morphPrefix.'_id'),
Loading history...
79 48
            'user_type'        => $this->getAttribute($morphPrefix.'_type'),
80
        ];
81
82 48
        if ($this->user) {
83 33
            foreach ($this->user->getArrayableAttributes() as $attribute => $value) {
84 33
                $this->data['user_'.$attribute] = $value;
85
            }
86
        }
87
88 48
        $this->metadata = array_keys($this->data);
89
90
        // Modified Auditable attributes
91 48
        foreach ($this->new_values as $key => $value) {
92 39
            $this->data['new_'.$key] = $value;
93
        }
94
95 48
        foreach ($this->old_values as $key => $value) {
96 9
            $this->data['old_'.$key] = $value;
97
        }
98
99 48
        $this->modified = array_diff_key(array_keys($this->data), $this->metadata);
100
101 48
        return $this->data;
102
    }
103
104
    /**
105
     * Get the formatted value of an Eloquent model.
106
     *
107
     * @param Model  $model
108
     * @param string $key
109
     * @param mixed  $value
110
     *
111
     * @return mixed
112
     */
113 30
    protected function getFormattedValue(Model $model, string $key, $value)
114
    {
115
        // Apply defined get mutator
116 30
        if ($model->hasGetMutator($key)) {
117 27
            return $model->mutateAttribute($key, $value);
118
        }
119
120
        // Cast to native PHP type
121 30
        if ($model->hasCast($key)) {
122 18
            return $model->castAttribute($key, $value);
123
        }
124
125
        // Honour DateTime attribute
126 30
        if ($value !== null && in_array($key, $model->getDates(), true)) {
127 15
            return $model->asDateTime($value);
128
        }
129
130 30
        return $value;
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136 36
    public function getDataValue(string $key)
137
    {
138 36
        if (!array_key_exists($key, $this->data)) {
139 3
            return;
140
        }
141
142 36
        $value = $this->data[$key];
143
144
        // User value
145 36
        if ($this->user && starts_with($key, 'user_')) {
146 9
            return $this->getFormattedValue($this->user, substr($key, 5), $value);
147
        }
148
149
        // Auditable value
150 36
        if ($this->auditable && starts_with($key, ['new_', 'old_'])) {
151 24
            $attribute = substr($key, 4);
152
153 24
            return $this->getFormattedValue(
154 24
                $this->auditable,
155 24
                $attribute,
156 24
                $this->decodeAttributeValue($this->auditable, $attribute, $value)
157
            );
158
        }
159
160 12
        return $value;
161
    }
162
163
    /**
164
     * Decode attribute value.
165
     *
166
     * @param Contracts\Auditable $auditable
167
     * @param string              $attribute
168
     * @param mixed               $value
169
     *
170
     * @return mixed
171
     */
172 24
    protected function decodeAttributeValue(Contracts\Auditable $auditable, string $attribute, $value)
173
    {
174 24
        $attributeModifiers = $auditable->getAttributeModifiers();
175
176 24
        if (!array_key_exists($attribute, $attributeModifiers)) {
177 24
            return $value;
178
        }
179
180 3
        $attributeDecoder = $attributeModifiers[$attribute];
181
182 3
        if (is_subclass_of($attributeDecoder, AttributeEncoder::class)) {
183 3
            return call_user_func([$attributeDecoder, 'decode'], $value);
184
        }
185
186 3
        return $value;
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 12
    public function getMetadata(bool $json = false, int $options = 0, int $depth = 512)
193
    {
194 12
        if (empty($this->data)) {
195 12
            $this->resolveData();
196
        }
197
198 12
        $metadata = [];
199
200 12
        foreach ($this->metadata as $key) {
201 12
            $value = $this->getDataValue($key);
202
203 12
            $metadata[$key] = $value instanceof DateTimeInterface
204 6
                ? $this->serializeDate($value)
205 12
                : $value;
206
        }
207
208 12
        return $json ? json_encode($metadata, $options, $depth) : $metadata;
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214 27
    public function getModified(bool $json = false, int $options = 0, int $depth = 512)
215
    {
216 27
        if (empty($this->data)) {
217 27
            $this->resolveData();
218
        }
219
220 27
        $modified = [];
221
222 27
        foreach ($this->modified as $key) {
223 21
            $attribute = substr($key, 4);
224 21
            $state = substr($key, 0, 3);
225
226 21
            $value = $this->getDataValue($key);
227
228 21
            $modified[$attribute][$state] = $value instanceof DateTimeInterface
229 6
                ? $this->serializeDate($value)
230 21
                : $value;
231
        }
232
233 27
        return $json ? json_encode($modified, $options, $depth) : $modified;
234
    }
235
236
    /**
237
     * Get the Audit tags as an array.
238
     *
239
     * @return array
240
     */
241 6
    public function getTags(): array
242
    {
243 6
        return preg_split('/,/', $this->tags, null, PREG_SPLIT_NO_EMPTY);
0 ignored issues
show
Bug Best Practice introduced by
The expression return preg_split('/,/',...ng\PREG_SPLIT_NO_EMPTY) could return the type false which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
244
    }
245
}
246