Passed
Push — master ( 859454...486cab )
by Smoren
01:57
created

QueryRelationManager::select()   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
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Smoren\QueryRelationManager\Yii2;
4
5
use Smoren\QueryRelationManager\Base\QueryRelationManagerBase;
6
use Smoren\QueryRelationManager\Base\QueryWrapperInterface;
7
use Smoren\QueryRelationManager\Base\QueryRelationManagerException;
8
use yii\base\InvalidConfigException;
9
use yii\db\ActiveQuery;
10
use yii\db\ActiveRecord;
11
12
/**
13
 * QueryRelationManager implementation for ActiveRecord в Yii2
14
 * @author Smoren <[email protected]>
15
 * @inheritDoc
16
 */
17
class QueryRelationManager extends QueryRelationManagerBase
18
{
19
    /**
20
     * @var QueryWrapper ActiveQuery wrapper instance
21
     */
22
    protected QueryWrapperInterface $query;
23
24
    /**
25
     * @inheritDoc
26
     */
27
    public static function select(string $className, string $tableAlias): QueryRelationManagerBase
28
    {
29
        static::checkClassIsActiveRecord($className);
30
        return parent::select($className, $tableAlias);
31
    }
32
33
    /**
34
     * Connects table to query as a relation using ActiveRecord relation config
35
     * @param string $relationName relation name from ActiveRecord relation config
36
     * @param string $relationAlias alias of joined table
37
     * @param string|null $parentAlias alias of table to join to (by default: main table of query)
38
     * @param string $joinType join type ("inner", "left", "right")
39
     * @param string|null $extraJoinCondition extra join conditions
40
     * @param array<string, scalar> $extraJoinParams values of dynamic properties of extra join conditions
41
     * @return $this
42
     * @throws QueryRelationManagerException
43
     */
44
    public function with(
45
        string $relationName,
46
        string $relationAlias,
47
        ?string $parentAlias = null,
48
        string $joinType = 'left',
49
        ?string $extraJoinCondition = null,
50
        array $extraJoinParams = []
51
    ): self {
52
        $mainTable = $this->tableCollection->getMainTable();
53
54
        $parentAlias = $parentAlias ?? $mainTable->alias;
55
        $parentClassName = $this->tableCollection->byAlias($parentAlias)->className;
56
        static::checkClassIsActiveRecord($parentClassName);
57
58
        /** @var ActiveRecord $inst */
59
        $inst = new $parentClassName();
60
        $methodName = 'get'.ucfirst($relationName);
61
        if(!method_exists($inst, $methodName)) {
62
            throw new QueryRelationManagerException("method {$parentClassName}::{$methodName}() not exists");
63
        }
64
65
        /** @var ActiveQuery $activeQuery */
66
        $activeQuery = $inst->$methodName();
67
        if(!($activeQuery instanceof ActiveQuery)) {
0 ignored issues
show
introduced by
$activeQuery is always a sub-type of yii\db\ActiveQuery.
Loading history...
68
            throw new QueryRelationManagerException(
69
                "method {$parentClassName}::{$methodName}() returned non-ActiveQuery instance"
70
            );
71
        }
72
73
        if($activeQuery->via) {
74
            throw new QueryRelationManagerException('cannot use relations with "via" section yet');
75
        }
76
        if(!is_array($activeQuery->link) || !count($activeQuery->link)) {
0 ignored issues
show
introduced by
The condition is_array($activeQuery->link) is always true.
Loading history...
77
            throw new QueryRelationManagerException('cannot use relations without "link" section');
78
        }
79
80
        /** @var string $className */
81
        $className = $activeQuery->modelClass;
82
83
        if($activeQuery->multiple) {
84
            return $this->withMultiple(
85
                $relationName,
86
                $className,
87
                $relationAlias,
88
                $parentAlias,
89
                $activeQuery->link,
90
                $joinType,
91
                $extraJoinCondition,
92
                $extraJoinParams
93
            );
94
        } else {
95
            return $this->withSingle(
96
                $relationName,
97
                $className,
98
                $relationAlias,
99
                $parentAlias,
100
                $activeQuery->link,
101
                $joinType,
102
                $extraJoinCondition,
103
                $extraJoinParams
104
            );
105
        }
106
    }
107
108
    /**
109
     * @inheritDoc
110
     * @return QueryWrapper
111
     */
112
    public function prepare(): QueryWrapper
113
    {
114
        /** @var QueryWrapper $wrapper */
115
        $wrapper = parent::prepare();
116
        return $wrapper;
117
    }
118
119
    /**
120
     * @param string $className
121
     * @return void
122
     * @throws QueryRelationManagerException
123
     */
124
    protected static function checkClassIsActiveRecord(string $className)
125
    {
126
        if(!class_exists($className)) {
127
            throw new QueryRelationManagerException(
128
                "class '{$className}' does not exist"
129
            );
130
        }
131
132
        if(!(new $className() instanceof ActiveRecord)) {
133
            throw new QueryRelationManagerException(
134
                "class {$className} is not an instance of ActiveRecord"
135
            );
136
        }
137
    }
138
139
    /**
140
     * Returns table name by it's ActiveRecord class name
141
     * @param string $className ActiveRecord class name
142
     * @return string table name
143
     * @throws QueryRelationManagerException
144
     */
145
    protected function getTableName(string $className): string
146
    {
147
        static::checkClassIsActiveRecord($className);
148
        return $className::tableName();
149
    }
150
151
    /**
152
     * @inheritDoc
153
     * @return QueryWrapper
154
     */
155
    protected function createQuery(): QueryWrapper
156
    {
157
        return new QueryWrapper();
158
    }
159
160
    /**
161
     * @inheritDoc
162
     * @throws QueryRelationManagerException|InvalidConfigException
163
     */
164
    protected function getTableFields(string $className): array
165
    {
166
        static::checkClassIsActiveRecord($className);
167
        /**
168
         * @var ActiveRecord $className
169
         * @var array<string, mixed> $columns
170
         */
171
        $columns = $className::getTableSchema()->columns;
172
        return array_keys($columns);
173
    }
174
175
    /**
176
     * @inheritDoc
177
     * @throws QueryRelationManagerException
178
     */
179
    protected function getPrimaryKey(string $className): array
180
    {
181
        static::checkClassIsActiveRecord($className);
182
        /** @var ActiveRecord $className */
183
        return $className::primaryKey();
184
    }
185
}
186