IsConcatenableRelation::mergeExpressions()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 10
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Traits\Concatenation;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\PostgresConnection;
8
use RuntimeException;
9
10
trait IsConcatenableRelation
11
{
12
    /**
13
     * Append the relation's through parents, foreign and local keys to a deep relationship.
14
     *
15
     * @param \Illuminate\Database\Eloquent\Model[] $through
16
     * @param array $foreignKeys
17
     * @param array $localKeys
18
     * @param int $position
19
     * @return array
20
     */
21 168
    public function appendToDeepRelationship(array $through, array $foreignKeys, array $localKeys, int $position): array
22
    {
23 168
        if ($position === 0) {
24 150
            $foreignKeys[] = function (Builder $query, ?Builder $parentQuery = null) {
25 78
                if ($parentQuery) {
26 30
                    $this->getRelationExistenceQuery($this->query, $parentQuery);
0 ignored issues
show
Bug introduced by
It seems like getRelationExistenceQuery() 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

26
                    $this->/** @scrutinizer ignore-call */ 
27
                           getRelationExistenceQuery($this->query, $parentQuery);
Loading history...
27
                }
28
29 78
                $this->mergeExpressions($query, $this->query);
30 150
            };
31
32 150
            $localKeys[] = null;
33
        } else {
34 18
            throw new RuntimeException(
35 18
                sprintf(
36 18
                    '%s can only be at the beginning of deep relationships at the moment.',
37 18
                    class_basename($this)
38 18
                )
39 18
            );
40
        }
41
42 150
        return [$through, $foreignKeys, $localKeys];
43
    }
44
45
    /**
46
     * Get the related table name for a deep relationship.
47
     *
48
     * @return string
49
     */
50 150
    public function getTableForDeepRelationship(): string
51
    {
52 150
        return $this->related->getExpressionName();
53
    }
54
55
    /**
56
     * The custom callback to run at the end of the get() method.
57
     *
58
     * @param \Illuminate\Database\Eloquent\Collection $models
59
     * @return void
60
     */
61 120
    public function postGetCallback(Collection $models): void
62
    {
63 120
        if (!$this->query->getConnection() instanceof PostgresConnection) {
64 100
            return;
65
        }
66
67 20
        if (!isset($models[0]->laravel_through_key)) {
68 3
            return;
69
        }
70
71 17
        $this->replacePathSeparator(
72 17
            $models,
73 17
            'laravel_through_key',
74 17
            $this->related->getPathSeparator()
75 17
        );
76
    }
77
78
    /**
79
     * Replace the separator in a PostgreSQL path column.
80
     *
81
     * @param \Illuminate\Database\Eloquent\Collection $models
82
     * @param string $column
83
     * @param string $separator
84
     * @return void
85
     */
86 17
    protected function replacePathSeparator(Collection $models, string $column, string $separator): void
87
    {
88 17
        foreach ($models as $model) {
89 17
            $model->$column = str_replace(
90 17
                ',',
91 17
                $separator,
92 17
                substr($model->$column, 1, -1)
93 17
            );
94
        }
95
    }
96
97
    /**
98
     * Get the custom through key for an eager load of the relation.
99
     *
100
     * @param string $alias
101
     * @return string
102
     */
103 120
    public function getThroughKeyForDeepRelationships(string $alias): string
104
    {
105 120
        $throughKey = $this->related->qualifyColumn(
106 120
            $this->related->getPathName()
107 120
        );
108
109 120
        return "$throughKey as $alias";
110
    }
111
112
    /**
113
     * Merge the common table expressions from one query into another.
114
     *
115
     * @param \Illuminate\Database\Eloquent\Builder $query
116
     * @param \Illuminate\Database\Eloquent\Builder $from
117
     * @return \Illuminate\Database\Eloquent\Builder
118
     */
119 150
    protected function mergeExpressions(Builder $query, Builder $from): Builder
120
    {
121 150
        $query->getQuery()->expressions = array_merge(
0 ignored issues
show
Bug introduced by
The property expressions does not seem to exist on Illuminate\Database\Query\Builder.
Loading history...
122 150
            $query->getQuery()->expressions,
123 150
            $from->getQuery()->expressions
124 150
        );
125
126 150
        return $query->addBinding(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->addBindin...sions'], 'expressions') could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
127 150
            $from->getQuery()->getRawBindings()['expressions'],
128 150
            'expressions'
129 150
        );
130
    }
131
}
132