JoinsThroughParents   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
eloc 35
c 1
b 0
f 0
dl 0
loc 98
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A joinThroughParent() 0 35 5
A throughParentInstanceSoftDeletes() 0 3 1
A throughParentJoins() 0 25 5
1
<?php
2
3
namespace Staudenmeir\EloquentHasManyDeep\Eloquent\Relations\Traits;
4
5
use Closure;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\SoftDeletes;
9
use Illuminate\Database\Query\JoinClause;
10
use Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey;
11
12
trait JoinsThroughParents
13
{
14
    /**
15
     * Join a through parent table.
16
     *
17
     * @param \Illuminate\Database\Eloquent\Builder $query
18
     * @param \Illuminate\Database\Eloquent\Model $throughParent
19
     * @param \Illuminate\Database\Eloquent\Model $predecessor
20
     * @param \Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey|array|string $foreignKey
21
     * @param \Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey|array|string $localKey
22
     * @param string $prefix
23
     * @return void
24
     */
25
    protected function joinThroughParent(Builder $query, Model $throughParent, Model $predecessor, $foreignKey, $localKey, $prefix)
26
    {
27
        $table = $throughParent->getTable();
28
29
        if ($foreignKey instanceof Closure) {
0 ignored issues
show
introduced by
$foreignKey is never a sub-type of Closure.
Loading history...
30
            $query->join(
31
                $table,
32
                fn (JoinClause $join) => $foreignKey($query, $join)
33
            );
34
        } else {
35
            $joins = $this->throughParentJoins($query, $throughParent, $predecessor, $foreignKey, $localKey);
36
37
            foreach ($joins as $i => [$first, $second]) {
38
                $joins[$i] = [
39
                    $throughParent->qualifyColumn($first),
40
                    $predecessor->qualifyColumn($prefix.$second),
41
                ];
42
            }
43
44
            $query->join(
45
                $table,
46
                function (JoinClause $join) use ($joins) {
47
                    foreach ($joins as [$first, $second]) {
48
                        $join->on($first, '=', $second);
49
                    }
50
                }
51
            );
52
        }
53
54
        if ($this->throughParentInstanceSoftDeletes($throughParent)) {
55
            /** @phpstan-ignore method.notFound */
56
            $column = $throughParent->getQualifiedDeletedAtColumn();
57
58
            $query->withGlobalScope(__CLASS__ . ":$column", function (Builder $query) use ($column) {
59
                $query->whereNull($column);
60
            });
61
        }
62
    }
63
64
    /**
65
     * Get the joins for a through parent table.
66
     *
67
     * @param \Illuminate\Database\Eloquent\Builder $query
68
     * @param \Illuminate\Database\Eloquent\Model $throughParent
69
     * @param \Illuminate\Database\Eloquent\Model $predecessor
70
     * @param \Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey|array|string $foreignKey
71
     * @param \Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey|array|string $localKey
72
     * @return array
73
     */
74
    protected function throughParentJoins(Builder $query, Model $throughParent, Model $predecessor, $foreignKey, $localKey): array
75
    {
76
        $joins = [];
77
78
        if ($localKey instanceof CompositeKey) {
79
            foreach ($localKey->columns as $i => $column) {
80
                $joins[] = [$column, $foreignKey->columns[$i]];
81
            }
82
        } else {
83
            if (is_array($localKey)) {
84
                $query->where($throughParent->qualifyColumn($localKey[0]), '=', $predecessor->getMorphClass());
85
86
                $localKey = $localKey[1];
87
            }
88
89
            if (is_array($foreignKey)) {
90
                $query->where($predecessor->qualifyColumn($foreignKey[0]), '=', $throughParent->getMorphClass());
91
92
                $foreignKey = $foreignKey[1];
93
            }
94
95
            $joins[] = [$localKey, $foreignKey];
96
        }
97
98
        return $joins;
99
    }
100
101
    /**
102
     * Determine whether a "through" parent instance of the relation uses SoftDeletes.
103
     *
104
     * @param \Illuminate\Database\Eloquent\Model $instance
105
     * @return bool
106
     */
107
    public function throughParentInstanceSoftDeletes(Model $instance)
108
    {
109
        return in_array(SoftDeletes::class, class_uses_recursive($instance));
110
    }
111
}
112