Passed
Pull Request — master (#312)
by Arman
03:23
created

Join::joinThrough()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.8
13
 */
14
15
namespace Quantum\Libraries\Database\Adapters\Sleekdb\Statements;
16
17
use Quantum\Libraries\Database\Adapters\Sleekdb\SleekDbal;
18
use Quantum\Libraries\Database\Contracts\DbalInterface;
19
use SleekDB\Exceptions\InvalidArgumentException;
20
use Quantum\Model\Exceptions\ModelException;
21
use Quantum\Model\QtModel;
22
use SleekDB\QueryBuilder;
23
24
/**
25
 * Trait Join
26
 * @package Quantum\Libraries\Database
27
 */
28
trait Join
29
{
30
31
    /**
32
     * @inheritDoc
33
     */
34
    public function joinTo(QtModel $model, bool $switch = true): DbalInterface
35
    {
36
        $this->addJoin(__FUNCTION__, $model, $switch);
37
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Quantum\Libraries\Databa...Sleekdb\Statements\Join which is incompatible with the type-hinted return Quantum\Libraries\Database\Contracts\DbalInterface.
Loading history...
38
    }
39
40
    /**
41
     * @inheritDoc
42
     */
43
    public function joinThrough(QtModel $model, bool $switch = true): DbalInterface
44
    {
45
        $this->addJoin(__FUNCTION__, $model, $switch);
46
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Quantum\Libraries\Databa...Sleekdb\Statements\Join which is incompatible with the type-hinted return Quantum\Libraries\Database\Contracts\DbalInterface.
Loading history...
47
    }
48
49
    /**
50
     * Adds join
51
     * @param string $type
52
     * @param QtModel $model
53
     * @param bool $switch
54
     */
55
    private function addJoin(string $type, QtModel $model, bool $switch = true)
56
    {
57
        $this->joins[] = [
0 ignored issues
show
Bug Best Practice introduced by
The property joins does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
58
            'type' => $type,
59
            'model' => serialize($model),
60
            'switch' => $switch,
61
        ];
62
    }
63
64
    /**
65
     * Starts to apply joins
66
     * @throws ModelException
67
     */
68
    private function applyJoins()
69
    {
70
        if (isset($this->joins[0])) {
71
            $this->applyJoin($this->queryBuilder, $this, $this->joins[0]);
72
        }
73
    }
74
75
    /**
76
     * Apply the join to query builder
77
     * @param QueryBuilder $queryBuilder
78
     * @param SleekDbal $currentItem
79
     * @param array $nextItem
80
     * @param int $level
81
     * @return QueryBuilder
82
     * @throws ModelException
83
     */
84
    private function applyJoin(QueryBuilder $queryBuilder, SleekDbal $currentItem, array $nextItem, int $level = 1): QueryBuilder
85
    {
86
        $modelToJoin = unserialize($nextItem['model']);
87
        $switch = $nextItem['switch'];
88
        $joinType = $nextItem['type'];
89
90
        $queryBuilder->join(function ($item) use ($currentItem, $modelToJoin, $switch, $joinType, $level) {
91
92
            $sleekModel = new self($modelToJoin->table, get_class($modelToJoin), $modelToJoin->idColumn, $modelToJoin->relations());
0 ignored issues
show
Unused Code introduced by
The call to Quantum\Libraries\Databa...nts\Join::__construct() has too many arguments starting with $modelToJoin->table. ( Ignorable by Annotation )

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

92
            $sleekModel = /** @scrutinizer ignore-call */ new self($modelToJoin->table, get_class($modelToJoin), $modelToJoin->idColumn, $modelToJoin->relations());

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
93
94
            $newQueryBuilder = $sleekModel->getOrmModel()->createQueryBuilder();
0 ignored issues
show
Bug introduced by
It seems like getOrmModel() 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

94
            $newQueryBuilder = $sleekModel->/** @scrutinizer ignore-call */ getOrmModel()->createQueryBuilder();
Loading history...
95
96
            if ($joinType == self::JOINTO) {
0 ignored issues
show
Bug introduced by
The constant Quantum\Libraries\Databa...Statements\Join::JOINTO was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
97
                $this->applyJoinTo($newQueryBuilder, $modelToJoin, $currentItem, $item);
98
            } else if ($joinType == self::JOINTHROUGH) {
0 ignored issues
show
Bug introduced by
The constant Quantum\Libraries\Databa...ments\Join::JOINTHROUGH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
99
                $this->applyJoinThrough($newQueryBuilder, $modelToJoin, $currentItem, $item);
100
            }
101
102
            if ($switch && isset($this->joins[$level])) {
103
                $this->applyJoin($newQueryBuilder, $sleekModel, $this->joins[$level], $level + 1);
104
            }
105
106
            return $newQueryBuilder;
107
108
        }, $modelToJoin->table);
109
110
        if (!$switch && isset($this->joins[$level])) {
111
            $this->applyJoin($queryBuilder, $currentItem, $this->joins[$level], $level + 1);
112
        }
113
114
        return $queryBuilder;
115
    }
116
117
    /**
118
     * Apply join condition for JOINTO type
119
     * @param QueryBuilder $queryBuilder
120
     * @param QtModel $modelToJoin
121
     * @param SleekDbal $currentItem
122
     * @param array $item
123
     * @return void
124
     * @throws InvalidArgumentException
125
     * @throws ModelException
126
     */
127
    private function applyJoinTo(QueryBuilder $queryBuilder, QtModel $modelToJoin, SleekDbal $currentItem, array $item): void
128
    {
129
        $foreignKeys = $modelToJoin->relations();
130
        $relatedModelName = $currentItem->getModelName();
131
132
        if (!isset($foreignKeys[$relatedModelName])) {
133
            throw ModelException::wrongRelation(get_class($modelToJoin), $relatedModelName);
134
        }
135
136
        $queryBuilder->where([
137
            $foreignKeys[$relatedModelName]['foreign_key'],
138
            '=',
139
            $item[$foreignKeys[$relatedModelName]['local_key']]
140
        ]);
141
    }
142
143
    /**
144
     * Apply join condition for JOINTHROUGH type
145
     * @param QueryBuilder $queryBuilder
146
     * @param QtModel $modelToJoin
147
     * @param SleekDbal $currentItem
148
     * @param array $item
149
     * @return void
150
     * @throws ModelException
151
     * @throws InvalidArgumentException
152
     */
153
    private function applyJoinThrough(QueryBuilder $queryBuilder, QtModel $modelToJoin, SleekDbal $currentItem, array $item): void
154
    {
155
        $foreignKeys = $currentItem->getForeignKeys();
156
        $relatedModelName = get_class($modelToJoin);
157
158
        if (!isset($foreignKeys[$relatedModelName])) {
159
            throw ModelException::wrongRelation($relatedModelName, $currentItem->getModelName());
160
        }
161
162
        $queryBuilder->where([
163
            $foreignKeys[$relatedModelName]['local_key'],
164
            '=',
165
            $item[$foreignKeys[$relatedModelName]['foreign_key']]
166
        ]);
167
    }
168
}