Table::setPkFieldChain()   A
last analyzed

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 1
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Smoren\QueryRelationManager\Base\Structs;
4
5
use Smoren\QueryRelationManager\Base\QueryRelationManagerException;
6
7
/**
8
 * Class Table
9
 * Класс-хранилище данных о таблице, которая участвует в запросе
10
 * @author Smoren <[email protected]>
11
 */
12
class Table
13
{
14
    /**
15
     * @var string class of ORM model wrapping the table
16
     */
17
    public string $className;
18
19
    /**
20
     * @var string table name in DB
21
     */
22
    public string $name;
23
24
    /**
25
     * @var string table alias in query
26
     */
27
    public string $alias;
28
29
    /**
30
     * @var string[] fields of the primary key of the table
31
     */
32
    public array $primaryKey;
33
34
    /**
35
     * @var string|null container key of parent item to put the current item to
36
     */
37
    public ?string $containerFieldAlias;
38
39
    /**
40
     * @var array<string, string> table fields map ["tableAlias.fieldName" => "tableAlias_fieldName", ...]
41
     */
42
    protected array $fieldMap = [];
43
44
    /**
45
     * @var array<string, string> reverse table fields map ["tableAlias_fieldName" => "tableAlias.fieldName"]
46
     */
47
    protected array $fieldMapReverse = [];
48
49
    /**
50
     * @var array<string, string> reverse map of the fields of the primary key
51
     * e.g. ["tableAlias_fieldName" => "fieldName"]
52
     */
53
    protected array $pkFieldMapReverse = [];
54
55
    /**
56
     * @var array<string> chain of the primary key's fields of all the joined tables till current
57
     */
58
    protected array $pkFieldChain = [];
59
60
    /**
61
     * Table constructor.
62
     * @param string $className class of ORM model wrapping the table
63
     * @param string $name table name in DB
64
     * @param string $alias table alias in query
65
     * @param array<string> $fields list of fields of the table
66
     * @param array<string> $primaryKey fields of the primary key of the table
67
     * @param string|null $containerFieldAlias container key of parent item to put the current item to
68
     * @throws QueryRelationManagerException
69
     */
70
    public function __construct(
71
        string $className,
72
        string $name,
73
        string $alias,
74
        array $fields,
75
        array $primaryKey,
76
        ?string $containerFieldAlias = null
77
    ) {
78
        $this->className = $className;
79
        $this->name = $name;
80
        $this->alias = $alias;
81
        $this->primaryKey = $primaryKey;
82
        $this->containerFieldAlias = $containerFieldAlias;
83
84
        $bufMap = [];
85
        foreach($fields as $field) {
86
            $bufMap[$field] = "{$this->alias}_{$field}";
87
            $this->fieldMap["{$this->alias}.{$field}"] = "{$this->alias}_{$field}";
88
            $this->fieldMapReverse["{$this->alias}_{$field}"] = $field;
89
        }
90
91
        foreach($this->primaryKey as $field) {
92
            if(!isset($bufMap[$field])) {
93
                throw new QueryRelationManagerException("pk field {$field} not found in field list");
94
            }
95
            $this->pkFieldMapReverse[$bufMap[$field]] = $field;
96
        }
97
    }
98
99
    /**
100
     * Returns fields map of the table ["tableAlias.fieldName" => "tableAlias_fieldName", ...]
101
     * @return array<string>
102
     */
103
    public function getFieldMap(): array
104
    {
105
        return $this->fieldMap;
106
    }
107
108
    /**
109
     * Returns field name by it's prefixed name
110
     * @param string $fieldPrefixed prefixed field name (prefix is table alias)
111
     * @return string
112
     */
113
    public function getField(string $fieldPrefixed): string
114
    {
115
        return $this->fieldMapReverse[$fieldPrefixed];
116
    }
117
118
    /**
119
     * Returns string of primary key fields of the table imploded by '-'
120
     * @return string
121
     */
122
    public function stringifyPrimaryKey(): string
123
    {
124
        return implode('-', $this->primaryKey);
125
    }
126
127
    /**
128
     * Returns true if table row data isset in select-query result row
129
     * @param array<string, mixed> $row select-query result row
130
     * @return bool
131
     */
132
    public function issetDataInRow(array &$row): bool
133
    {
134
        foreach($this->pkFieldMapReverse as $prefixedKey => $key) {
135
            if($row[$prefixedKey] !== null) {
136
                return true;
137
            }
138
        }
139
        return false;
140
    }
141
142
    /**
143
     * Returns data from select-query result row
144
     * @param array<string, mixed> $row select-query result row
145
     * @param JoinConditionCollection $conditionCollection collection of join conditions of the select-query
146
     * @return array<mixed> [
147
     *  (array) "table row data from select-query result row",
148
     *  (string) "values of the primary key fields imploded by '-'",
149
     *  (string) "alias of current table",
150
     *  (string) "alias of table to join current table to",
151
     *  (string) "values of the foreign key fields imploded by '-'",
152
     *  (string) "container key of parent item to put the current item to",
153
     *  (int) "condition type for parent table (1 — 'one to one' или 2 — 'one to many')"
154
     * ]
155
     * @throws QueryRelationManagerException
156
     */
157
    public function getDataFromRow(array $row, JoinConditionCollection $conditionCollection): array
158
    {
159
        $item = [];
160
161
        foreach($this->fieldMapReverse as $fieldPrefixed => $field) {
162
            $item[$field] = $row[$fieldPrefixed];
163
        }
164
165
        /** @var JoinCondition $cond */
166
        foreach($conditionCollection->byJoinTo($this->alias) as $cond) {
167
            switch($cond->type) {
168
                case JoinCondition::TYPE_MULTIPLE:
169
                    $item[$cond->table->containerFieldAlias] = [];
170
                    break;
171
                case JoinCondition::TYPE_SINGLE:
172
                    $item[$cond->table->containerFieldAlias] = null;
173
                    break;
174
                default:
175
                    throw new QueryRelationManagerException("unknown condition type '{$cond->type}'");
176
            }
177
        }
178
179
        $primaryKeyValue = $this->stringifyPrimaryKeyValue($row);
180
181
        if($conditionCollection->issetByJoinAs($this->alias)) {
182
            $cond = $conditionCollection->byJoinAs($this->alias);
183
            $joinTo = $cond->joinTo;
184
            $aliasTo = $joinTo->alias;
185
            $foreignKeyValue = $joinTo->stringifyPrimaryKeyValue($row);
186
            $type = $cond->type;
187
        } else {
188
            $aliasTo = null;
189
            $foreignKeyValue = null;
190
            $containerFieldAlias = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $containerFieldAlias is dead and can be removed.
Loading history...
191
            $type = null;
192
        }
193
194
        return [$item, $primaryKeyValue, $this->alias, $aliasTo, $foreignKeyValue, $this->containerFieldAlias, $type];
195
    }
196
197
    /**
198
     * Returns list of primary key field names prefixed by table alias by dot
199
     * @return array<string>
200
     */
201
    public function getPrimaryKeyForSelect(): array
202
    {
203
        $result = [];
204
        foreach($this->primaryKey as $field) {
205
            $result[] = "{$this->alias}.{$field}";
206
        }
207
208
        return $result;
209
    }
210
211
    /**
212
     * Setter for chain of the primary key's fields of all the joined tables till current
213
     * @param array<string> $pkFieldChain primary key fields chain
214
     * @return $this
215
     */
216
    public function setPkFieldChain(array $pkFieldChain): self
217
    {
218
        $this->pkFieldChain = $pkFieldChain;
219
        return $this;
220
    }
221
222
    /**
223
     * Returns values of the table primary key as a string imploded by '-'
224
     * @param array<string, mixed> $row select-query result row
225
     * @return string
226
     */
227
    protected function stringifyPrimaryKeyValue(array $row): string
228
    {
229
        $primaryKeyValues = [];
230
231
        foreach($this->pkFieldChain as $field) {
232
            $primaryKeyValues[] = $row[$field];
233
        }
234
235
        return implode('-', $primaryKeyValues);
236
    }
237
}
238