Completed
Pull Request — master (#702)
by
unknown
03:08
created

ActivityLogger::setEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 5
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\Activitylog;
4
5
use Illuminate\Auth\AuthManager;
6
use Illuminate\Contracts\Config\Repository;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Carbon;
10
use Illuminate\Support\Str;
11
use Illuminate\Support\Traits\Macroable;
12
use Spatie\Activitylog\Contracts\Activity as ActivityContract;
13
use Spatie\Activitylog\Exceptions\CouldNotLogActivity;
14
15
class ActivityLogger
16
{
17
    use Macroable;
18
19
    /** @var \Illuminate\Auth\AuthManager */
20
    protected $auth;
21
22
    protected $defaultLogName = '';
23
24
    /** @var string */
25
    protected $authDriver;
26
27
    /** @var \Spatie\Activitylog\ActivityLogStatus */
28
    protected $logStatus;
29
30
    /** @var \Spatie\Activitylog\Contracts\Activity */
31
    protected $activity;
32 340
33
    public function __construct(AuthManager $auth, Repository $config, ActivityLogStatus $logStatus)
34 340
    {
35
        $this->auth = $auth;
36 340
37
        $this->authDriver = $config['activitylog']['default_auth_driver'] ?? $auth->getDefaultDriver();
38 340
39
        $this->defaultLogName = $config['activitylog']['default_log_name'];
40 340
41 340
        $this->logStatus = $logStatus;
42
    }
43 132
44
    public function setLogStatus(ActivityLogStatus $logStatus)
45 132
    {
46
        $this->logStatus = $logStatus;
47 132
48
        return $this;
49
    }
50 232
51
    public function performedOn(Model $model)
52 232
    {
53
        $this->getActivity()->subject()->associate($model);
54 232
55
        return $this;
56
    }
57 16
58
    public function on(Model $model)
59 16
    {
60
        return $this->performedOn($model);
61
    }
62 340
63
    public function causedBy($modelOrId)
64 340
    {
65 332
        if ($modelOrId === null) {
66
            return $this;
67
        }
68 44
69
        $model = $this->normalizeCauser($modelOrId);
70 44
71
        $this->getActivity()->causer()->associate($model);
72 44
73
        return $this;
74
    }
75 20
76
    public function by($modelOrId)
77 20
    {
78
        return $this->causedBy($modelOrId);
79
    }
80 8
81
    public function causedByAnonymous()
82 8
    {
83 8
        $this->activity->causer_id = null;
0 ignored issues
show
Bug introduced by
Accessing causer_id on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
84
        $this->activity->causer_type = null;
0 ignored issues
show
Bug introduced by
Accessing causer_type on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
85 8
86
        return $this;
87
    }
88 4
89
    public function byAnonymous()
90 4
    {
91
        return $this->causedByAnonymous();
92
    }
93 340
94
    public function event(string $event)
95 340
    {
96
        return $this->setEvent($event);
97 340
    }
98
99
    public function setEvent(string $event)
100 4
    {
101
        $this->activity->event = $event;
0 ignored issues
show
Bug introduced by
Accessing event on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
102 4
        return $this;
103
    }
104 4
105
    public function withProperties($properties)
106
    {
107 340
        $this->getActivity()->properties = collect($properties);
0 ignored issues
show
Bug introduced by
Accessing properties on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
108
109 340
        return $this;
110
    }
111 340
112
    public function withProperty(string $key, $value)
113
    {
114
        $this->getActivity()->properties = $this->getActivity()->properties->put($key, $value);
0 ignored issues
show
Bug introduced by
Accessing properties on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
115
116
        return $this;
117
    }
118
119 12
    public function createdAt(Carbon $dateTime)
120
    {
121 12
        $this->getActivity()->created_at = $dateTime;
0 ignored issues
show
Bug introduced by
Accessing created_at on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
122
123 12
        return $this;
124
    }
125
126 4
    public function useLog(string $logName)
127
    {
128 4
        $this->getActivity()->log_name = $logName;
0 ignored issues
show
Bug introduced by
Accessing log_name on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
129
130 4
        return $this;
131
    }
132
133 4
    public function inLog(string $logName)
134
    {
135 4
        return $this->useLog($logName);
136
    }
137 4
138
    public function tap(callable $callback, string $eventName = null)
139
    {
140 340
        call_user_func($callback, $this->getActivity(), $eventName);
141
142 340
        return $this;
143 8
    }
144
145
    public function enableLogging()
146 332
    {
147
        $this->logStatus->enable();
148 332
149 332
        return $this;
150 83
    }
151
152
    public function disableLogging()
153 332
    {
154
        $this->logStatus->disable();
155 332
156
        return $this;
157 332
    }
158
159
    public function log(string $description)
160 44
    {
161
        if ($this->logStatus->disabled()) {
162 44
            return;
163 40
        }
164
165
        $activity = $this->activity;
166 4
167 4
        $activity->description = $this->replacePlaceholders(
0 ignored issues
show
Bug introduced by
Accessing description on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
168 4
            $activity->description ?? $description,
0 ignored issues
show
Bug introduced by
Accessing description on the interface Spatie\Activitylog\Contracts\Activity suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
169
            $activity
170 4
        );
171 4
172
        $activity->save();
173
174
        $this->activity = null;
175
176
        return $activity;
177 332
    }
178
179
    public function withoutLogs(callable $callback)
180 12
    {
181
        if ($this->logStatus->disabled()) {
182 12
            return $callback();
183
        }
184 12
185 4
        $this->logStatus->disable();
186
187
        try {
188 8
            return $callback();
189
        } finally {
190 8
            $this->logStatus->enable();
191
        }
192 8
    }
193 4
194
    protected function normalizeCauser($modelOrId): Model
195
    {
196 4
        if ($modelOrId instanceof Model) {
197
            return $modelOrId;
198 4
        }
199 332
200
        $guard = $this->auth->guard($this->authDriver);
201
        $provider = method_exists($guard, 'getProvider') ? $guard->getProvider() : null;
202 340
        $model = method_exists($provider, 'retrieveById') ? $provider->retrieveById($modelOrId) : null;
203
204 340
        if ($model instanceof Model) {
205 340
            return $model;
206
        }
207 340
208 340
        throw CouldNotLogActivity::couldNotDetermineUser($modelOrId);
209 340
    }
210
211
    protected function replacePlaceholders(string $description, ActivityContract $activity): string
212 340
    {
213
        return preg_replace_callback('/:[a-z0-9._-]+/i', function ($match) use ($activity) {
214
            $match = $match[0];
215
216
            $attribute = Str::before(Str::after($match, ':'), '.');
217
218
            if (! in_array($attribute, ['subject', 'causer', 'properties'])) {
219
                return $match;
220
            }
221
222
            $propertyName = substr($match, strpos($match, '.') + 1);
223
224
            $attributeValue = $activity->$attribute;
225
226
            if (is_null($attributeValue)) {
227
                return $match;
228
            }
229
230
            $attributeValue = $attributeValue->toArray();
231
232
            return Arr::get($attributeValue, $propertyName, $match);
233
        }, $description);
234
    }
235
236
    protected function getActivity(): ActivityContract
237
    {
238
        if (! $this->activity instanceof ActivityContract) {
239
            $this->activity = ActivitylogServiceProvider::getActivityModelInstance();
240
            $this
241
                ->useLog($this->defaultLogName)
242
                ->withProperties([])
243
                ->causedBy($this->auth->guard($this->authDriver)->user());
244
        }
245
246
        return $this->activity;
247
    }
248
}
249