Failed Conditions
Pull Request — master (#59)
by Dallas
13:19
created

src/Relations/AbstractBelongsToTree.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Umbrellio\LTree\Relations;
6
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Database\Eloquent\Collection;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\Relations\Relation;
11
use Illuminate\Database\Query\JoinClause;
12
use Umbrellio\LTree\Interfaces\LTreeModelInterface;
13
use Umbrellio\LTree\Traits\LTreeModelTrait;
14
15
abstract class AbstractBelongsToTree extends Relation
16
{
17
    protected $throughRelationName;
18
    private $foreignKey;
19
    private $ownerKey;
20
21 3
    public function __construct(
22
        Builder $query,
23
        Model $child,
24
        string $throughRelationName,
25
        string $foreignKey,
26
        string $ownerKey
27
    ) {
28 3
        $this->throughRelationName = $throughRelationName;
29 3
        $this->foreignKey = $foreignKey;
30 3
        $this->ownerKey = $ownerKey;
31
32 3
        parent::__construct($query, $child);
33 3
    }
34
35 3
    public function addConstraints(): void
36
    {
37 3
        if (static::$constraints) {
38 3
            $relation = $this->parent->{$this->throughRelationName};
39
40 3
            if ($relation) {
41 3
                $this->query = $this->getQueryForTree($relation);
42
            }
43
        }
44 3
    }
45
46 3
    public function addEagerConstraints(array $models): void
47
    {
48 3
        $key = $this->related->getTable() . '.' . $this->ownerKey;
49
50 3
        $whereIn = $this->whereInMethod($this->related, $this->ownerKey);
51
52 3
        $this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
53
54
        $table = $this
55 3
            ->getModel()
0 ignored issues
show
The method getModel() does not exist on Umbrellio\LTree\Relations\AbstractBelongsToTree. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

55
            ->/** @scrutinizer ignore-call */ getModel()
Loading history...
56 3
            ->getTable();
57 3
        $alias = sprintf('%s_depends', $table);
58
59 3
        $related = $this->getLTreeRelated();
60
61 3
        $this->query->join(
62 3
            sprintf('%s as %s', $table, $alias),
63 3
            function (JoinClause $query) use ($alias, $table, $related) {
64 3
                $query->whereRaw(sprintf(
65 3
                    '%1$s.%2$s %4$s %3$s.%2$s',
66
                    $alias,
67 3
                    $related->getLtreePathColumn(),
68
                    $table,
69 3
                    $this->getOperator()
70
                ));
71 3
            }
72
        );
73
74 3
        $this->query->orderBy($related->getLtreePathColumn());
75
76 3
        $this->query->selectRaw(sprintf('%s.*, %s.%s as relation_id', $alias, $table, $this->ownerKey));
77 3
    }
78
79 3
    public function match(array $models, Collection $results, $relation)
80
    {
81 3
        $dictionary = [];
82
83 3
        foreach ($results as $result) {
84 3
            $dictionary[$result->relation_id][] = $result;
85
        }
86
87 3
        foreach ($models as $model) {
88 3
            foreach ($dictionary as $related => $value) {
89 3
                if ($model->getAttribute($this->foreignKey) === $related) {
90 3
                    $model->setRelation($relation, $this->related->newCollection($value));
91
                }
92
            }
93
        }
94
95 3
        return $models;
96
    }
97
98 3
    public function getResults()
99
    {
100 3
        return $this->getParentKey() !== null
101 3
            ? $this->query->get()
102 3
            : $this->related->newCollection();
103
    }
104
105
106
    /**
107
     * Initialize the relation on a set of models.
108
     *
109
     * @param string $relation
110
     * @return array
111
     */
112 3
    public function initRelation(array $models, $relation)
113
    {
114 3
        foreach ($models as $model) {
115 3
            $model->setRelation($relation, $this->related->newCollection());
116
        }
117
118 3
        return $models;
119
    }
120
121
    /**
122
     * @param Builder|LTreeModelTrait $model
123
     */
124
    abstract protected function getQueryForTree($model): Builder;
125
126
    abstract protected function getOperator(): string;
127
128 3
    protected function getEagerModelKeys(array $models)
129
    {
130 3
        $keys = [];
131
132 3
        foreach ($models as $model) {
133 3
            if (($value = $model->{$this->foreignKey}) !== null) {
134 3
                $keys[] = $value;
135
            }
136
        }
137
138 3
        sort($keys);
139
140 3
        return array_values(array_unique($keys));
141
    }
142
143 3
    protected function getLTreeRelated(): LTreeModelInterface
144
    {
145
        return $this
146 3
            ->parent
147 3
            ->{$this->throughRelationName}()
148 3
            ->related;
149
    }
150
151 3
    private function getParentKey()
152
    {
153 3
        return $this->parent->{$this->foreignKey};
154
    }
155
}
156