Completed
Push — master ( be1dc2...d56e9e )
by Vitaly
06:38
created

Query::entity()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 1 Features 6
Metric Value
cc 5
eloc 15
c 12
b 1
f 6
nc 9
nop 1
dl 0
loc 23
rs 8.5906
1
<?php declare(strict_types=1);
2
namespace samsonframework\orm;
3
use samson\activerecord\dbQuery;
4
5
/**
6
 * Database query builder.
7
 *
8
 * @author Vitaly Iegorov <[email protected]>
9
 * @\samsonframework\containerannotation\Service("query")
10
 */
11
class Query extends dbQuery implements QueryInterface
0 ignored issues
show
Deprecated Code introduced by
The class samson\activerecord\dbQuery has been deprecated with message: Should be removed ASAP in favor of generated classes or DI

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
12
{
13
    /** @var TableMetadata */
14
    protected $metadata;
15
16
    /** @var array Collection of parent table selected fields */
17
    protected $select = [];
18
19
    /** @var array Collection of entity field names for sorting order */
20
    protected $sorting = [];
21
22
    /** @var array Collection of entity field names for grouping query results */
23
    protected $grouping = [];
24
25
    /** @var array Collection of query results limitations */
26
    protected $limitation = [];
27
28
    /** @var TableMetadata[] Collection of joined entities */
29
    protected $joins = [];
30
31
    /** @var Condition Query entity condition group */
32
    protected $condition;
33
34
    /** @var DatabaseInterface Database instance */
35
    protected $database;
36
37
    /** @var SQLBuilder SQL builder */
38
    protected $sqlBuilder;
39
40
    /**
41
     * Query constructor.
42
     *
43
     * @param               Database Database instance
44
     * @param SQLBuilder    $sqlBuilder
45
     *
46
     * @\samsonframework\containerannotation\InjectArgument(database="\samsonframework\orm\Database")
47
     * @\samsonframework\containerannotation\InjectArgument(sqlBuilder="\samsonframework\orm\SQLBuilder")
48
     */
49
    public function __construct(Database $database, SQLBuilder $sqlBuilder)
50
    {
51
        $this->database = $database;
52
        $this->sqlBuilder = $sqlBuilder;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function find() : array
59
    {
60
        return $this->database->fetchObjects($this->buildSQL(), $this->metadata->className, $this->metadata->primaryField);
61
    }
62
63
    /**
64
     * Build SQL statement from this query.
65
     *
66
     * @return string SQL statement
67
     * @throws \InvalidArgumentException
68
     */
69
    protected function buildSQL() : string
70
    {
71
        // If none fields are selected - select all fields from parent table
72
        $this->select = count($this->select) ? $this->select : [$this->metadata->tableName => '*'];
73
74
        $sql = $this->sqlBuilder->buildSelectStatement($this->select);
75
        $sql .= "\n" . $this->sqlBuilder->buildFromStatement(
76
                array_merge(array_keys($this->select), array_keys($this->joins))
77
            );
78
        $sql .= "\n" . 'WHERE ' . $this->sqlBuilder->buildWhereStatement($this->metadata, $this->condition);
79
80
        if (count($this->grouping)) {
81
            $sql .= "\n" . $this->sqlBuilder->buildGroupStatement($this->grouping);
82
        }
83
84
        if (count($this->sorting)) {
85
            $sql .= "\n" . $this->sqlBuilder->buildOrderStatement($this->sorting[0], $this->sorting[1]);
86
        }
87
88
        if (count($this->limitation)) {
89
            $sql .= "\n" . $this->sqlBuilder->buildLimitStatement($this->limitation[0], $this->limitation[1]);
90
        }
91
92
        return $sql;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function count() : int
99
    {
100
        return $this->database->count($this->buildSQL());
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function first()
107
    {
108
        $return = $this->limit(1)->exec();
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::exec() has been deprecated with message: Use self::find()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
109
110
        return count($return) ? array_shift($return) : null;
0 ignored issues
show
Bug Compatibility introduced by
The expression count($return) ? array_shift($return) : null; of type samson\activerecord\RecordInterface|null adds the type samson\activerecord\RecordInterface to the return on line 110 which is incompatible with the return type declared by the interface samsonframework\orm\QueryInterface::first of type boolean|samsonframework\orm\RecordInterface.
Loading history...
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function limit(int $quantity, int $offset = 0) : QueryInterface
117
    {
118
        $this->limitation = [$quantity, $offset];
119
120
        // Chaining
121
        return $this;
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127
    public function fields(string $fieldName) : array
128
    {
129
        // Return bool or collection
130
        return $this->database->fetchColumn($this->buildSQL(), $this->metadata->getTableColumnIndex($fieldName));
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function entity($metadata) : QueryInterface
137
    {
138
        if (is_string($metadata)) {
139
            // Remove old namespace
140
            $metadata = strpos($metadata, '\samson\activerecord\\') !== false ? str_replace('\samson\activerecord\\', '', $metadata) : $metadata;
141
            $metadata = strpos($metadata, 'samson\activerecord\\') !== false ? str_replace('samson\activerecord\\', '', $metadata) : $metadata;
142
            // Capitalize and add cms namespace
143
            $metadata = strpos($metadata, '\\') === false ? 'samsoncms\api\generated\\' . ucfirst($metadata) : $metadata;
144
145
            $this->metadata = TableMetadata::fromClassName($metadata);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\TableMetadata::fromClassName() has been deprecated with message: This is temporary old approach

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
146
        } else {
147
            $this->metadata = $metadata;
148
        }
149
150
        $this->select = [];
151
        $this->joins = [];
152
        $this->grouping = [];
153
        $this->limitation = [];
154
        $this->sorting = [];
155
        $this->condition = new Condition();
156
157
        return $this;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function orderBy(string $tableName, string $fieldName, string $order = 'ASC') : QueryInterface
164
    {
165
        $this->sorting[$tableName][] = [$fieldName, $order];
166
167
        // Chaining
168
        return $this;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function whereCondition(ConditionInterface $condition) : QueryInterface
175
    {
176
        $this->condition->addCondition($condition);
177
178
        return $this;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function select(string $tableName, string $fieldName) : QueryInterface
185
    {
186
        $this->select[$tableName][] = $fieldName;
187
188
        return $this;
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function join(string $entityName) : QueryInterface
195
    {
196
        $this->joins[$entityName] = [];
197
198
        // Chaining
199
        return $this;
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    public function groupBy(string $tableName, string $fieldName) : QueryInterface
206
    {
207
        $this->grouping[$tableName][] = $fieldName;
208
209
        // Chaining
210
        return $this;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function isNull(string $fieldName) : QueryInterface
217
    {
218
        return $this->where($fieldName, '', ArgumentInterface::ISNULL);
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224
    public function where(
225
        string $fieldName,
226
        $fieldValue = null,
227
        string $relation = ArgumentInterface::EQUAL
228
    ) : QueryInterface
229
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
230
        // Add condition argument
231
        $this->condition->add($fieldName, $fieldValue, $relation);
232
233
        return $this;
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239
    public function notNull(string $fieldName) : QueryInterface
240
    {
241
        return $this->where($fieldName, '', ArgumentInterface::NOTNULL);
242
    }
243
244
    /**
245
     * {@inheritdoc}
246
     */
247
    public function notEmpty(string $fieldName) : QueryInterface
248
    {
249
        return $this->where($fieldName, '', ArgumentInterface::NOT_EQUAL);
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255
    public function like(string $fieldName, string $value = '') : QueryInterface
256
    {
257
        return $this->where($fieldName, $value, ArgumentInterface::LIKE);
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263
    public function primary($value) : QueryInterface
264
    {
265
        return $this->where($this->metadata->primaryField, $value);
266
    }
267
}
268