Passed
Push — master ( 2be340...cdee59 )
by Jonas
13:41
created

IsConcatenableRelation::postGetCallback()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 3
nop 1
crap 3
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 135
    public function appendToDeepRelationship(array $through, array $foreignKeys, array $localKeys, int $position): array
22
    {
23 135
        if ($position === 0) {
24 120
            $foreignKeys[] = function (Builder $query, Builder $parentQuery = null) {
25 70
                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 70
                $this->mergeExpressions($query, $this->query);
30
            };
31
32 120
            $localKeys[] = null;
33
        } else {
34 15
            throw new RuntimeException(
35 15
                sprintf(
36
                    '%s can only be at the beginning of deep relationships at the moment.',
37 15
                    class_basename($this)
38
                )
39
            );
40
        }
41
42 120
        return [$through, $foreignKeys, $localKeys];
43
    }
44
45
    /**
46
     * Get the related table name for a deep relationship.
47
     *
48
     * @return string
49
     */
50 120
    public function getTableForDeepRelationship(): string
51
    {
52 120
        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 90
    public function postGetCallback(Collection $models): void
62
    {
63 90
        if (!$this->query->getConnection() instanceof PostgresConnection) {
64 72
            return;
65
        }
66
67 18
        if (!isset($models[0]->laravel_through_key)) {
68 3
            return;
69
        }
70
71 15
        $this->replacePathSeparator(
72
            $models,
73
            'laravel_through_key',
74 15
            $this->related->getPathSeparator()
75
        );
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 15
    protected function replacePathSeparator(Collection $models, string $column, string $separator): void
87
    {
88 15
        foreach ($models as $model) {
89 15
            $model->$column = str_replace(
90
                ',',
91
                $separator,
92 15
                substr($model->$column, 1, -1)
93
            );
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 90
    public function getThroughKeyForDeepRelationships(string $alias): string
104
    {
105 90
        $throughKey = $this->related->qualifyColumn(
106 90
            $this->related->getPathName()
107
        );
108
109 90
        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 120
    protected function mergeExpressions(Builder $query, Builder $from): Builder
120
    {
121 120
        $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 120
            $query->getQuery()->expressions,
123 120
            $from->getQuery()->expressions
124
        );
125
126 120
        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 120
            $from->getQuery()->getRawBindings()['expressions'],
128
            'expressions'
129
        );
130
    }
131
}
132