GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Joiner   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
dl 0
loc 192
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 9

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A join() 0 10 2
A leftJoin() 0 4 1
A rightJoin() 0 4 1
A joinSegment() 0 16 4
A alreadyJoined() 0 4 1
A getJoinClause() 0 20 5
A joinIntermediate() 0 16 3
B getJoinKeys() 0 24 6
1
<?php
2
3
namespace Sofa\Eloquence\Relations;
4
5
use Illuminate\Database\Eloquent\Relations\MorphMany;
6
use LogicException;
7
use Illuminate\Database\Query\Builder;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Database\Eloquent\SoftDeletes;
10
use Illuminate\Database\Query\JoinClause as Join;
11
use Illuminate\Database\Eloquent\Relations\MorphTo;
12
use Illuminate\Database\Eloquent\Relations\Relation;
13
use Illuminate\Database\Eloquent\Relations\BelongsTo;
14
use Illuminate\Database\Eloquent\Relations\MorphToMany;
15
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
16
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
17
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
18
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
19
use Sofa\Eloquence\Contracts\Relations\Joiner as JoinerContract;
20
21
class Joiner implements JoinerContract
22
{
23
    /**
24
     * Processed query instance.
25
     *
26
     * @var Builder
27
     */
28
    protected $query;
29
30
    /**
31
     * Parent model.
32
     *
33
     * @var Model
34
     */
35
    protected $model;
36
37
    /**
38
     * Create new joiner instance.
39
     *
40
     * @param Builder $query
41
     * @param Model $model
42
     */
43
    public function __construct(Builder $query, Model $model)
44
    {
45
        $this->query = $query;
46
        $this->model = $model;
47
    }
48
49
    /**
50
     * Join related tables.
51
     *
52
     * @param  string $target
53
     * @param  string $type
54
     * @return Model
55
     */
56
    public function join($target, $type = 'inner')
57
    {
58
        $related = $this->model;
59
60
        foreach (explode('.', $target) as $segment) {
61
            $related = $this->joinSegment($related, $segment, $type);
62
        }
63
64
        return $related;
65
    }
66
67
    /**
68
     * Left join related tables.
69
     *
70
     * @param  string $target
71
     * @return Model
72
     */
73
    public function leftJoin($target)
74
    {
75
        return $this->join($target, 'left');
76
    }
77
78
    /**
79
     * Right join related tables.
80
     *
81
     * @param  string $target
82
     * @return Model
83
     */
84
    public function rightJoin($target)
85
    {
86
        return $this->join($target, 'right');
87
    }
88
89
    /**
90
     * Join relation's table accordingly.
91
     *
92
     * @param Model $parent
93
     * @param  string $segment
94
     * @param  string $type
95
     * @return Model
96
     */
97
    protected function joinSegment(Model $parent, $segment, $type)
98
    {
99
        $relation = $parent->{$segment}();
100
        $related = $relation->getRelated();
101
        $table = $related->getTable();
102
103
        if ($relation instanceof BelongsToMany || $relation instanceof HasManyThrough) {
104
            $this->joinIntermediate($parent, $relation, $type);
105
        }
106
107
        if (!$this->alreadyJoined($join = $this->getJoinClause($parent, $relation, $table, $type))) {
108
            $this->query->joins[] = $join;
109
        }
110
111
        return $related;
112
    }
113
114
    /**
115
     * Determine whether the related table has been already joined.
116
     *
117
     * @param Join $join
118
     * @return bool
119
     */
120
    protected function alreadyJoined(Join $join)
121
    {
122
        return in_array($join, (array) $this->query->joins);
123
    }
124
125
    /**
126
     * Get the join clause for related table.
127
     *
128
     * @param Model $parent
129
     * @param Relation $relation
130
     * @param  string $type
131
     * @param  string $table
132
     * @return Join
133
     */
134
    protected function getJoinClause(Model $parent, Relation $relation, $table, $type)
135
    {
136
        [$fk, $pk] = $this->getJoinKeys($relation);
0 ignored issues
show
Bug introduced by
The variable $fk does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $pk does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
137
138
        $join = (new Join($this->query, $type, $table))->on($fk, '=', $pk);
139
140
        /** @var Model|SoftDeletes $related */
141
        $related = $relation->getRelated();
142
        if (method_exists($related, 'getQualifiedDeletedAtColumn')) {
143
            $join->whereNull($related->getQualifiedDeletedAtColumn());
0 ignored issues
show
Bug introduced by
The method getQualifiedDeletedAtColumn does only exist in Illuminate\Database\Eloquent\SoftDeletes, but not in Illuminate\Database\Eloquent\Model.

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...
144
        }
145
146
        if ($relation instanceof MorphOneOrMany) {
147
            $join->where($relation->getQualifiedMorphType(), '=', $parent->getMorphClass());
148
        } elseif ($relation instanceof MorphToMany || $relation instanceof MorphMany) {
149
            $join->where($relation->getMorphType(), '=', $parent->getMorphClass());
150
        }
151
152
        return $join;
153
    }
154
155
    /**
156
     * Join pivot or 'through' table.
157
     *
158
     * @param Model $parent
159
     * @param Relation $relation
160
     * @param  string $type
161
     * @return void
162
     */
163
    protected function joinIntermediate(Model $parent, Relation $relation, $type)
164
    {
165
        if ($relation instanceof BelongsToMany) {
166
            $table = $relation->getTable();
167
            $fk = $relation->getQualifiedForeignPivotKeyName();
168
        } else {
169
            $table = $relation->getParent()->getTable();
170
            $fk = $relation->getQualifiedFirstKeyName();
171
        }
172
173
        $pk = $parent->getQualifiedKeyName();
174
175
        if (!$this->alreadyJoined($join = (new Join($this->query, $type, $table))->on($fk, '=', $pk))) {
176
            $this->query->joins[] = $join;
177
        }
178
    }
179
180
    /**
181
     * Get pair of the keys from relation in order to join the table.
182
     *
183
     * @param Relation $relation
184
     * @return array
185
     *
186
     * @throws LogicException
187
     */
188
    protected function getJoinKeys(Relation $relation)
189
    {
190
        if ($relation instanceof MorphTo) {
191
            throw new LogicException('MorphTo relation cannot be joined.');
192
        }
193
194
        if ($relation instanceof HasOneOrMany) {
195
            return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedParentKeyName()];
196
        }
197
198
        if ($relation instanceof BelongsTo) {
199
            return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedOwnerKeyName()];
200
        }
201
202
        if ($relation instanceof BelongsToMany) {
203
            return [$relation->getQualifiedRelatedPivotKeyName(), $relation->getRelated()->getQualifiedKeyName()];
204
        }
205
206
        if ($relation instanceof HasManyThrough) {
207
            $fk = $relation->getQualifiedFarKeyName();
208
209
            return [$fk, $relation->getQualifiedParentKeyName()];
210
        }
211
    }
212
}
213