Completed
Push — blameable-update ( 9d2a46...a5aed9 )
by Richan
04:56
created

BlameableTrait::useSoftDeletes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace RichanFongdasen\EloquentBlameable;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\SoftDeletes;
8
9
trait BlameableTrait
10
{
11
    /**
12
     * Get any of override 'blameable attributes'.
13
     *
14
     * @return array
15
     */
16
    public function blameable()
17
    {
18
        if (property_exists($this, 'blameable')) {
19
            return (array) static::$blameable;
20
        }
21
        return [];
22
    }
23
24
    /**
25
     * Boot the Blameable service by attaching
26
     * a new observer into the current model object.
27
     *
28
     * @return void
29
     */
30
    public static function bootBlameableTrait()
31
    {
32
        static::observe(app(BlameableObserver::class));
33
    }
34
35
    /**
36
     * Build blameable query scope.
37
     *
38
     * @param \Illuminate\Database\Eloquent\Builder $query
39
     * @param mixed                                 $userId
40
     * @param string                                $key
41
     *
42
     * @return \Illuminate\Database\Eloquent\Builder
43
     */
44
    private function buildBlameableScope(Builder $query, $userId, $key)
45
    {
46
        if ($userId instanceof Model) {
47
            $userId = $userId->getKey();
48
        }
49
50
        return $query->where(app(BlameableService::class)->getConfiguration($this, $key), $userId);
51
    }
52
53
    /**
54
     * Get the user who created the record.
55
     *
56
     * @return \Illuminate\Database\Eloquent\Model
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Database\Eloquent\Relations\BelongsTo?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
57
     */
58
    public function creator()
59
    {
60
        return $this->belongsTo(
61
            app(BlameableService::class)->getConfiguration($this, 'user'),
62
            app(BlameableService::class)->getConfiguration($this, 'createdBy')
63
        );
64
    }
65
66
    /**
67
     * Get the user who updated the record for the last time.
68
     *
69
     * @return \Illuminate\Database\Eloquent\Model
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Database\Eloquent\Relations\BelongsTo?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
70
     */
71
    public function updater()
72
    {
73
        return $this->belongsTo(
74
            app(BlameableService::class)->getConfiguration($this, 'user'),
75
            app(BlameableService::class)->getConfiguration($this, 'updatedBy')
76
        );
77
    }
78
79
    /**
80
     * createdBy Query Scope.
81
     *
82
     * @param \Illuminate\Database\Eloquent\Builder $query
83
     * @param mixed                                 $userId
84
     *
85
     * @return \Illuminate\Database\Eloquent\Builder
86
     */
87
    public function scopeCreatedBy(Builder $query, $userId)
88
    {
89
        return $this->buildBlameableScope($query, $userId, 'createdBy');
90
    }
91
92
    /**
93
     * updatedBy Query Scope.
94
     *
95
     * @param \Illuminate\Database\Eloquent\Builder $query
96
     * @param mixed                                 $userId
97
     *
98
     * @return \Illuminate\Database\Eloquent\Builder
99
     */
100
    public function scopeUpdatedBy(Builder $query, $userId)
101
    {
102
        return $this->buildBlameableScope($query, $userId, 'updatedBy');
103
    }
104
105
    /**
106
     * Silently update the model without firing any
107
     * events.
108
     *
109
     * @return int
110
     */
111
    public function silentUpdate()
112
    {
113
        if (!$this->isDirty()) {
0 ignored issues
show
Bug introduced by
It seems like isDirty() must be provided by classes using this trait. How about adding it as abstract method to this trait?

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

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). 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.

Loading history...
114
            return 0;
115
        }
116
117
        return $this->newQueryWithoutScopes()
1 ignored issue
show
Bug introduced by
The method where does only exist in Illuminate\Database\Eloquent\Builder, but not in RichanFongdasen\EloquentBlameable\BlameableTrait.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
118
            ->where($this->getKeyName(), $this->getKey())
119
            ->getQuery()
120
            ->update($this->getDirty());
121
    }
122
123
    /**
124
     * Confirm if the current model uses SoftDeletes.
125
     *
126
     * @return boolean
127
     */
128
    public function useSoftDeletes()
129
    {
130
        return in_array(SoftDeletes::class, class_uses($this));
131
    }
132
133
    /**
134
     * Define an inverse one-to-one or many relationship.
135
     *
136
     * @param string $related
137
     * @param string $foreignKey
0 ignored issues
show
Documentation introduced by
Should the type for parameter $foreignKey not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
138
     * @param string $otherKey
0 ignored issues
show
Documentation introduced by
Should the type for parameter $otherKey not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
139
     * @param string $relation
0 ignored issues
show
Documentation introduced by
Should the type for parameter $relation not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
140
     *
141
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
142
     */
143
    abstract public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null);
144
145
    /**
146
     * Get the attributes that have been changed since last sync.
147
     *
148
     * @return array
149
     */
150
    abstract public function getDirty();
151
152
    /**
153
     * Get the primary key for the model.
154
     *
155
     * @return string
156
     */
157
    abstract public function getKeyName();
158
159
    /**
160
     * Get the value of the model's primary key.
161
     *
162
     * @return mixed
163
     */
164
    abstract public function getKey();
165
166
    /**
167
     * Get a new query builder that doesn't have any global scopes.
168
     *
169
     * @return \Illuminate\Database\Eloquent\Builder|static
170
     */
171
    abstract public function newQueryWithoutScopes();
172
}
173